modesp.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. /*
  2. * This file is part of the MicroPython project, http://micropython.org/
  3. *
  4. * The MIT License (MIT)
  5. *
  6. * Copyright (c) 2015 Paul Sokolovsky
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. #include <stdio.h>
  27. #include "py/gc.h"
  28. #include "py/runtime.h"
  29. #include "py/mperrno.h"
  30. #include "py/mphal.h"
  31. #include "drivers/dht/dht.h"
  32. #include "uart.h"
  33. #include "user_interface.h"
  34. #include "mem.h"
  35. #include "ets_alt_task.h"
  36. #include "espneopixel.h"
  37. #include "espapa102.h"
  38. #include "modmachine.h"
  39. #define MODESP_INCLUDE_CONSTANTS (1)
  40. void error_check(bool status, const char *msg) {
  41. if (!status) {
  42. nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, msg));
  43. }
  44. }
  45. STATIC mp_obj_t esp_osdebug(mp_obj_t val) {
  46. if (val == mp_const_none) {
  47. uart_os_config(-1);
  48. } else {
  49. uart_os_config(mp_obj_get_int(val));
  50. }
  51. return mp_const_none;
  52. }
  53. STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_osdebug_obj, esp_osdebug);
  54. STATIC mp_obj_t esp_sleep_type(size_t n_args, const mp_obj_t *args) {
  55. if (n_args == 0) {
  56. return mp_obj_new_int(wifi_get_sleep_type());
  57. } else {
  58. wifi_set_sleep_type(mp_obj_get_int(args[0]));
  59. return mp_const_none;
  60. }
  61. }
  62. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_sleep_type_obj, 0, 1, esp_sleep_type);
  63. STATIC mp_obj_t esp_deepsleep(size_t n_args, const mp_obj_t *args) {
  64. uint32_t sleep_us = n_args > 0 ? mp_obj_get_int(args[0]) : 0;
  65. // prepare for RTC reset at wake up
  66. rtc_prepare_deepsleep(sleep_us);
  67. system_deep_sleep_set_option(n_args > 1 ? mp_obj_get_int(args[1]) : 0);
  68. system_deep_sleep(sleep_us);
  69. return mp_const_none;
  70. }
  71. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_deepsleep_obj, 0, 2, esp_deepsleep);
  72. STATIC mp_obj_t esp_flash_id() {
  73. return mp_obj_new_int(spi_flash_get_id());
  74. }
  75. STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_id_obj, esp_flash_id);
  76. STATIC mp_obj_t esp_flash_read(mp_obj_t offset_in, mp_obj_t len_or_buf_in) {
  77. mp_int_t offset = mp_obj_get_int(offset_in);
  78. mp_int_t len;
  79. byte *buf;
  80. bool alloc_buf = MP_OBJ_IS_INT(len_or_buf_in);
  81. if (alloc_buf) {
  82. len = mp_obj_get_int(len_or_buf_in);
  83. buf = m_new(byte, len);
  84. } else {
  85. mp_buffer_info_t bufinfo;
  86. mp_get_buffer_raise(len_or_buf_in, &bufinfo, MP_BUFFER_WRITE);
  87. len = bufinfo.len;
  88. buf = bufinfo.buf;
  89. }
  90. // We know that allocation will be 4-byte aligned for sure
  91. SpiFlashOpResult res = spi_flash_read(offset, (uint32_t*)buf, len);
  92. if (res == SPI_FLASH_RESULT_OK) {
  93. if (alloc_buf) {
  94. return mp_obj_new_bytes(buf, len);
  95. }
  96. return mp_const_none;
  97. }
  98. if (alloc_buf) {
  99. m_del(byte, buf, len);
  100. }
  101. mp_raise_OSError(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO);
  102. }
  103. STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_read_obj, esp_flash_read);
  104. STATIC mp_obj_t esp_flash_write(mp_obj_t offset_in, const mp_obj_t buf_in) {
  105. mp_int_t offset = mp_obj_get_int(offset_in);
  106. mp_buffer_info_t bufinfo;
  107. mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
  108. if (bufinfo.len & 0x3) {
  109. mp_raise_ValueError("len must be multiple of 4");
  110. }
  111. ets_loop_iter(); // flash access takes time so run any pending tasks
  112. SpiFlashOpResult res = spi_flash_write(offset, bufinfo.buf, bufinfo.len);
  113. ets_loop_iter();
  114. if (res == SPI_FLASH_RESULT_OK) {
  115. return mp_const_none;
  116. }
  117. mp_raise_OSError(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO);
  118. }
  119. STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_write_obj, esp_flash_write);
  120. STATIC mp_obj_t esp_flash_erase(mp_obj_t sector_in) {
  121. mp_int_t sector = mp_obj_get_int(sector_in);
  122. ets_loop_iter(); // flash access takes time so run any pending tasks
  123. SpiFlashOpResult res = spi_flash_erase_sector(sector);
  124. ets_loop_iter();
  125. if (res == SPI_FLASH_RESULT_OK) {
  126. return mp_const_none;
  127. }
  128. mp_raise_OSError(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO);
  129. }
  130. STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_flash_erase_obj, esp_flash_erase);
  131. STATIC mp_obj_t esp_flash_size(void) {
  132. extern char flashchip;
  133. // For SDK 1.5.2, either address has shifted and not mirrored in
  134. // eagle.rom.addr.v6.ld, or extra initial member was added.
  135. SpiFlashChip *flash = (SpiFlashChip*)(&flashchip + 4);
  136. #if 0
  137. printf("deviceId: %x\n", flash->deviceId);
  138. printf("chip_size: %u\n", flash->chip_size);
  139. printf("block_size: %u\n", flash->block_size);
  140. printf("sector_size: %u\n", flash->sector_size);
  141. printf("page_size: %u\n", flash->page_size);
  142. printf("status_mask: %u\n", flash->status_mask);
  143. #endif
  144. return mp_obj_new_int_from_uint(flash->chip_size);
  145. }
  146. STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_size_obj, esp_flash_size);
  147. // If there's just 1 loadable segment at the start of flash,
  148. // we assume there's a yaota8266 bootloader.
  149. #define IS_OTA_FIRMWARE() ((*(uint32_t*)0x40200000 & 0xff00) == 0x100)
  150. extern byte _firmware_size[];
  151. STATIC mp_obj_t esp_flash_user_start(void) {
  152. return MP_OBJ_NEW_SMALL_INT((uint32_t)_firmware_size);
  153. }
  154. STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_user_start_obj, esp_flash_user_start);
  155. STATIC mp_obj_t esp_check_fw(void) {
  156. MD5_CTX ctx;
  157. char *fw_start = (char*)0x40200000;
  158. if (IS_OTA_FIRMWARE()) {
  159. // Skip yaota8266 bootloader
  160. fw_start += 0x3c000;
  161. }
  162. uint32_t size = *(uint32_t*)(fw_start + 0x8ffc);
  163. printf("size: %d\n", size);
  164. if (size > 1024 * 1024) {
  165. printf("Invalid size\n");
  166. return mp_const_false;
  167. }
  168. MD5Init(&ctx);
  169. MD5Update(&ctx, fw_start + 4, size - 4);
  170. unsigned char digest[16];
  171. MD5Final(digest, &ctx);
  172. printf("md5: ");
  173. for (int i = 0; i < 16; i++) {
  174. printf("%02x", digest[i]);
  175. }
  176. printf("\n");
  177. return mp_obj_new_bool(memcmp(digest, fw_start + size, sizeof(digest)) == 0);
  178. }
  179. STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_check_fw_obj, esp_check_fw);
  180. STATIC mp_obj_t esp_neopixel_write_(mp_obj_t pin, mp_obj_t buf, mp_obj_t is800k) {
  181. mp_buffer_info_t bufinfo;
  182. mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
  183. esp_neopixel_write(mp_obj_get_pin_obj(pin)->phys_port,
  184. (uint8_t*)bufinfo.buf, bufinfo.len, mp_obj_is_true(is800k));
  185. return mp_const_none;
  186. }
  187. STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_neopixel_write_obj, esp_neopixel_write_);
  188. #if MICROPY_ESP8266_APA102
  189. STATIC mp_obj_t esp_apa102_write_(mp_obj_t clockPin, mp_obj_t dataPin, mp_obj_t buf) {
  190. mp_buffer_info_t bufinfo;
  191. mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
  192. esp_apa102_write(mp_obj_get_pin_obj(clockPin)->phys_port,
  193. mp_obj_get_pin_obj(dataPin)->phys_port,
  194. (uint8_t*)bufinfo.buf, bufinfo.len);
  195. return mp_const_none;
  196. }
  197. STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_apa102_write_obj, esp_apa102_write_);
  198. #endif
  199. STATIC mp_obj_t esp_freemem() {
  200. return MP_OBJ_NEW_SMALL_INT(system_get_free_heap_size());
  201. }
  202. STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_freemem_obj, esp_freemem);
  203. STATIC mp_obj_t esp_meminfo() {
  204. system_print_meminfo();
  205. return mp_const_none;
  206. }
  207. STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_meminfo_obj, esp_meminfo);
  208. STATIC mp_obj_t esp_malloc(mp_obj_t size_in) {
  209. return MP_OBJ_NEW_SMALL_INT((mp_uint_t)os_malloc(mp_obj_get_int(size_in)));
  210. }
  211. STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_malloc_obj, esp_malloc);
  212. STATIC mp_obj_t esp_free(mp_obj_t addr_in) {
  213. os_free((void*)mp_obj_get_int(addr_in));
  214. return mp_const_none;
  215. }
  216. STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_free_obj, esp_free);
  217. STATIC mp_obj_t esp_esf_free_bufs(mp_obj_t idx_in) {
  218. return MP_OBJ_NEW_SMALL_INT(ets_esf_free_bufs(mp_obj_get_int(idx_in)));
  219. }
  220. STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_esf_free_bufs_obj, esp_esf_free_bufs);
  221. #if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA
  222. // We provide here a way of committing executable data to a region from
  223. // which it can be executed by the CPU. There are 2 such writable regions:
  224. // - iram1, which may have some space left at the end of it
  225. // - memory-mapped flash rom
  226. //
  227. // By default the iram1 region (the space at the end of it) is used. The
  228. // user can select iram1 or a section of flash by calling the
  229. // esp.set_native_code_location() function; see below. If flash is selected
  230. // then it is erased as needed.
  231. #include "gccollect.h"
  232. #define IRAM1_END (0x40108000)
  233. #define FLASH_START (0x40200000)
  234. #define FLASH_END (0x40300000)
  235. #define FLASH_SEC_SIZE (4096)
  236. #define ESP_NATIVE_CODE_IRAM1 (0)
  237. #define ESP_NATIVE_CODE_FLASH (1)
  238. extern uint32_t _lit4_end;
  239. STATIC uint32_t esp_native_code_location;
  240. STATIC uint32_t esp_native_code_start;
  241. STATIC uint32_t esp_native_code_end;
  242. STATIC uint32_t esp_native_code_cur;
  243. STATIC uint32_t esp_native_code_erased;
  244. void esp_native_code_init(void) {
  245. esp_native_code_location = ESP_NATIVE_CODE_IRAM1;
  246. esp_native_code_start = (uint32_t)&_lit4_end;
  247. esp_native_code_end = IRAM1_END;
  248. esp_native_code_cur = esp_native_code_start;
  249. esp_native_code_erased = 0;
  250. }
  251. void esp_native_code_gc_collect(void) {
  252. void *src;
  253. if (esp_native_code_location == ESP_NATIVE_CODE_IRAM1) {
  254. src = (void*)esp_native_code_start;
  255. } else {
  256. src = (void*)(FLASH_START + esp_native_code_start);
  257. }
  258. gc_collect_root(src, (esp_native_code_end - esp_native_code_start) / sizeof(uint32_t));
  259. }
  260. void *esp_native_code_commit(void *buf, size_t len) {
  261. //printf("COMMIT(buf=%p, len=%u, start=%08x, cur=%08x, end=%08x, erased=%08x)\n", buf, len, esp_native_code_start, esp_native_code_cur, esp_native_code_end, esp_native_code_erased);
  262. len = (len + 3) & ~3;
  263. if (esp_native_code_cur + len > esp_native_code_end) {
  264. nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError,
  265. "memory allocation failed, allocating %u bytes for native code", (uint)len));
  266. }
  267. void *dest;
  268. if (esp_native_code_location == ESP_NATIVE_CODE_IRAM1) {
  269. dest = (void*)esp_native_code_cur;
  270. memcpy(dest, buf, len);
  271. } else {
  272. SpiFlashOpResult res;
  273. while (esp_native_code_erased < esp_native_code_cur + len) {
  274. ets_loop_iter(); // flash access takes time so run any pending tasks
  275. res = spi_flash_erase_sector(esp_native_code_erased / FLASH_SEC_SIZE);
  276. if (res != SPI_FLASH_RESULT_OK) {
  277. break;
  278. }
  279. esp_native_code_erased += FLASH_SEC_SIZE;
  280. }
  281. ets_loop_iter();
  282. if (res == SPI_FLASH_RESULT_OK) {
  283. res = spi_flash_write(esp_native_code_cur, buf, len);
  284. ets_loop_iter();
  285. }
  286. if (res != SPI_FLASH_RESULT_OK) {
  287. mp_raise_OSError(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO);
  288. }
  289. dest = (void*)(FLASH_START + esp_native_code_cur);
  290. }
  291. esp_native_code_cur += len;
  292. return dest;
  293. }
  294. STATIC mp_obj_t esp_set_native_code_location(mp_obj_t start_in, mp_obj_t len_in) {
  295. if (start_in == mp_const_none && len_in == mp_const_none) {
  296. // use end of iram1 region
  297. esp_native_code_init();
  298. } else {
  299. // use flash; input params are byte offsets from start of flash
  300. esp_native_code_location = ESP_NATIVE_CODE_FLASH;
  301. esp_native_code_start = mp_obj_get_int(start_in);
  302. esp_native_code_end = esp_native_code_start + mp_obj_get_int(len_in);
  303. esp_native_code_cur = esp_native_code_start;
  304. esp_native_code_erased = esp_native_code_start;
  305. // memory-mapped flash is limited in extents to 1MByte
  306. if (esp_native_code_end > FLASH_END - FLASH_START) {
  307. mp_raise_ValueError("flash location must be below 1MByte");
  308. }
  309. }
  310. return mp_const_none;
  311. }
  312. STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_set_native_code_location_obj, esp_set_native_code_location);
  313. #endif
  314. STATIC const mp_rom_map_elem_t esp_module_globals_table[] = {
  315. { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_esp) },
  316. { MP_ROM_QSTR(MP_QSTR_osdebug), MP_ROM_PTR(&esp_osdebug_obj) },
  317. { MP_ROM_QSTR(MP_QSTR_sleep_type), MP_ROM_PTR(&esp_sleep_type_obj) },
  318. { MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&esp_deepsleep_obj) },
  319. { MP_ROM_QSTR(MP_QSTR_flash_id), MP_ROM_PTR(&esp_flash_id_obj) },
  320. { MP_ROM_QSTR(MP_QSTR_flash_read), MP_ROM_PTR(&esp_flash_read_obj) },
  321. { MP_ROM_QSTR(MP_QSTR_flash_write), MP_ROM_PTR(&esp_flash_write_obj) },
  322. { MP_ROM_QSTR(MP_QSTR_flash_erase), MP_ROM_PTR(&esp_flash_erase_obj) },
  323. { MP_ROM_QSTR(MP_QSTR_flash_size), MP_ROM_PTR(&esp_flash_size_obj) },
  324. { MP_ROM_QSTR(MP_QSTR_flash_user_start), MP_ROM_PTR(&esp_flash_user_start_obj) },
  325. #if MICROPY_ESP8266_NEOPIXEL
  326. { MP_ROM_QSTR(MP_QSTR_neopixel_write), MP_ROM_PTR(&esp_neopixel_write_obj) },
  327. #endif
  328. #if MICROPY_ESP8266_APA102
  329. { MP_ROM_QSTR(MP_QSTR_apa102_write), MP_ROM_PTR(&esp_apa102_write_obj) },
  330. #endif
  331. { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
  332. { MP_ROM_QSTR(MP_QSTR_freemem), MP_ROM_PTR(&esp_freemem_obj) },
  333. { MP_ROM_QSTR(MP_QSTR_meminfo), MP_ROM_PTR(&esp_meminfo_obj) },
  334. { MP_ROM_QSTR(MP_QSTR_check_fw), MP_ROM_PTR(&esp_check_fw_obj) },
  335. { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&pyb_info_obj) }, // TODO delete/rename/move elsewhere
  336. { MP_ROM_QSTR(MP_QSTR_malloc), MP_ROM_PTR(&esp_malloc_obj) },
  337. { MP_ROM_QSTR(MP_QSTR_free), MP_ROM_PTR(&esp_free_obj) },
  338. { MP_ROM_QSTR(MP_QSTR_esf_free_bufs), MP_ROM_PTR(&esp_esf_free_bufs_obj) },
  339. #if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA
  340. { MP_ROM_QSTR(MP_QSTR_set_native_code_location), MP_ROM_PTR(&esp_set_native_code_location_obj) },
  341. #endif
  342. #if MODESP_INCLUDE_CONSTANTS
  343. { MP_ROM_QSTR(MP_QSTR_SLEEP_NONE), MP_ROM_INT(NONE_SLEEP_T) },
  344. { MP_ROM_QSTR(MP_QSTR_SLEEP_LIGHT), MP_ROM_INT(LIGHT_SLEEP_T) },
  345. { MP_ROM_QSTR(MP_QSTR_SLEEP_MODEM), MP_ROM_INT(MODEM_SLEEP_T) },
  346. #endif
  347. };
  348. STATIC MP_DEFINE_CONST_DICT(esp_module_globals, esp_module_globals_table);
  349. const mp_obj_module_t esp_module = {
  350. .base = { &mp_type_module },
  351. .globals = (mp_obj_dict_t*)&esp_module_globals,
  352. };