%\begin{content} \chapter{添加 micropython 解释器} 从 \href{http://svn.zmd.com/svn/一部软件库/公共模块/micropython-c6x}{micropython-c6x} SVN 仓库获取项目最新的源码。 在将源代码下的 \texttt{ports/c6x/lib/upy.c6x.ae66} 添加到 AppRun 工程下的 lib 目录。 并修改 module.cmd,添加一行: \begin{minted}[bgcolor=lightgray!30,fontsize=\small]{c} -l ../lib/upy.c6x.ae66 \end{minted} %修改后的 module.cmd 内容如下: %\begin{minted}[bgcolor=lightgray!30,fontsize=\scriptsize]{ini} %-l ../lib/DrvUtils.lib %-l ../lib/upy.c6x.ae66 % %--diag_suppress=10068,10247 %--retain="*(.shellCommand)" % %SECTIONS %{ % .module_section: fill=0x0 align=0x4{ % module_ver_start=.; % *(.module_section) % module_ver_end=.; % }>DDR_RAM % % .dsp_cmd_section: fill = 0x0 align = 0x10 { % __console_cmd_start = .; % *(.dsp_cmd_section) % __console_cmd_end = .; % } > DDR_RAM % % .shell_command_section: fill = 0x0{ % _shell_command_start = .; % *(.shellCommand) % _shell_command_end = .; % } > DDR_RAM %} %\end{minted} \section{最小移植需求} 在 AppRun 工程中新建一个文件 mp\_port.c, 添加如下内容: \begin{minted}[bgcolor=lightgray!30,fontsize=\scriptsize]{c} #include /* {{{: console */ int mp_tic6x_console_readable() { return serialTstc(); } int mp_tic6x_console_getc() { return serialGetc(); } void mp_tic6x_console_putn(const char *str, size_t len) { while (len > 0) { serialPutc(*str++); --len; } } /* }}} */ \end{minted} 也可以通过实现 uart 的接口(mp\_tic6x\_uart\_readable, mp\_tic6x\_uart\_putc, mp\_tic6x\_uart\_getc) 中的第一个参数(uart\_id) 为-1时的功能来作为 REPL 的console。 在 AppRun.c 中添加 micropython 解释器的代码: \begin{minted}[bgcolor=lightgray!30,fontsize=\scriptsize]{c} /* {{{: upy interpreter */ void mp_tic6x_repl(unsigned char *, int len); #define GC_HEAP_SIZE 0x400000 static unsigned char gc_heap[GC_HEAP_SIZE]; void AppRun(void) { ... if (DNUM == 0) { ... mp_tic6x_repl(gc_heap, GC_HEAP_SIZE); ... } } /* }}} */ \end{minted} 这里 upy 的堆大小 GC\_HEAP\_SIZE 可根据实际需求进行修改。示例的代码中 0x400000 只起演示作用,不是硬性的大小限制。 \section{Flash 文件系统支持} upy 库默认添加了 FAT 和 LFS 支持,可以在 mp\_port.c 添加如下类似代码,实现文件系统的支持: \begin{minted}[bgcolor=lightgray!30,fontsize=\scriptsize]{c} /* {{{ tic6x.Flash */ #define BLOCK_SIZE_BYTES (0x20000) #define BPI_FLASH_REGBASE (0x70000000) #ifndef MICROPY_HW_FLASH_STORAGE_BYTES #define MICROPY_HW_FLASH_STORAGE_BYTES (0x200000) #endif #ifndef MICROPY_HW_FLASH_STORAGE_BASE #define MICROPY_HW_FLASH_STORAGE_BASE (0x600000) #endif #define FLASH_START_ADDRESS (BPI_FLASH_REGBASE + MICROPY_HW_FLASH_STORAGE_BASE) extern int norFlashFifoProgram(unsigned int nAddr, const unsigned char *pBuffer, unsigned int len); int mp_tic6x_flash_get_part_size(int part_id, unsigned int *blocks, unsigned int *block_size) { int r = 0; if (part_id == 0) { *blocks = (MICROPY_HW_FLASH_STORAGE_BYTES) / BLOCK_SIZE_BYTES; *block_size = BLOCK_SIZE_BYTES; } else { r = -1; } return (r); } int mp_tic6x_flash_read(int part_id, unsigned int sect_start, unsigned int sect_off, void *buf, size_t size) { unsigned char *srcbuf = (unsigned char *)(FLASH_START_ADDRESS); if (part_id != 0) { return -1; } srcbuf += sect_start * BLOCK_SIZE_BYTES + sect_off; memcpy(buf, srcbuf, size); return 0; } int mp_tic6x_flash_erase(int part_id, unsigned int block_start, unsigned int nblocks) { if (part_id != 0) { return -1; } return 0; } int mp_tic6x_flash_program(int part_id, unsigned int sect_start, unsigned int offset_in_sect, const void *buf, unsigned int size) { int r = 0; unsigned int lba; if (part_id != 0) { r = -1; goto end; } lba = MICROPY_HW_FLASH_STORAGE_BASE + sect_start * BLOCK_SIZE_BYTES + offset_in_sect; r = norFlashFifoProgram(lba, buf, size); end: return (r); } /* }}} */ \end{minted} 解释器在进入 REPL 之前,会先后自动运行文件系统上的名为 \textcolor{blue}{\texttt boot.py} 和 \textcolor{blue}{\texttt main.py} 的脚本文件。 \section{系统功能支持} 设置系统主频,复位和设备ID,可以在 mp\_port.c 中添加下列实现: \begin{minted}[bgcolor=lightgray!30,fontsize=\scriptsize]{c} /* {{{ machine.unique_id() */ int mp_tic6x_unique_id(uint8_t *buf, int len) { const char *board = getEnv("BOARD_INDEX"); if (board) { size_t slen = strlen(board); if (slen > len) slen = len; memcpy(buf, board, slen); return (slen); } return 0; } void sysReboot(); void mp_tic6x_hard_reset(void) { sysReboot(); } unsigned int mp_tic6x_get_cpu_freq() { return 1250000000UL; } /* }}} */ \end{minted} \section{符号表支持} 如果需要在 upy 支持直接调用程序的全局函数,可对 AppRun 工程做一点微小的修改来实现。 将 ports/c6x/include/symtbl.h 复制到 AppRun 的 h/user 目录下。 将 ports/c6x/lib/symgen目录下的 symgen.exe 和 symgen.lar 复制到 AppRun 的 bin 目录下,并在 该目录下新建一个空的名为 builtins.txt \label{sec:builtin} 的文件(该文件的用途后面再讲)。 将 ports/c6x/lib/symgen 下的 makefile.targets 文件复制到 AppRun 工程的最上面: \begin{table}[H] \centering \begin{tabular}{lcl} \toprule {\bf upy 工程} & & {\bf AppRun 工程} \\ \midrule ports/c6x/include/symtbl.h & -> & h/user/symtbl.h \\ ports/c6x/lib/symgen/symgen.exe & -> & bin/symgen.exe \\ ports/c6x/lib/symgen/symgen.lar & -> & bin/symgen.lar \\ ports/c6x/lib/symgen/makefile.targets & -> & makefile.targets \\ & new & bin/builtins.txt \\ \bottomrule \end{tabular} \caption{symbol 支持工程文件} \end{table} 如果有需要从符号表中排除一些接口,可以在 AppRun 的bin目录,创建一个名为 symgen.excl 的文件,将不需要的符号添加到该文件, 每行一个符号名。 文件添加后,AppRun 工程的文件如下图所示: \begin{figure}[H] \centering \includegraphics[width=0.5\textwidth]{symgen} \caption{symgen 文件位置} \end{figure} 图中的 symgen.lar 是 symgen.lua 用 lz4.exe 压缩得到的: \begin{minted}[bgcolor=lightgray!30,fontsize=\small]{bash} lz4.exe -9 symgen.lua symgen.lar \end{minted} 直接用 symgen.lua 文件也是可以的。 在 AppRun 工程上点击右键,分别选择 “Properties” => “Build” => “Behaviour”,将按下图红框所示进行配置: \begin{figure}[H] \centering \includegraphics[width=0.9\textwidth]{builder} \caption{编译 appsym 目标} \end{figure} 将添加了 micropython 解释器的工程最编译并烧写后,进入调试串口,看到如下类似打印: \begin{minted}[bgcolor=lightgray!30,fontsize=\scriptsize]{python} MicroPython ff67efa on 2022-07-20; C66xx with TIC6X Type "help()" for more information. >>> \end{minted} 则移植成功。可以输入 help() 查看帮助,输入 help('modules') 查看所支持的 Python 模块。 %生成的 bootloader 文件是: \texttt{image/A/bootloader.bin} 。 %在项目源码工程的 Tools 目录下有适合本项目的交叉编译器 gcc-linaro-6.1.1-2016.08-x86\_64\_aarch64-linux-gnu.tar.xz。 %先将其解压到 U-Boot 源码目录,然后编译: %\begin{minted}[bgcolor=lightgray!30,fontsize=\small]{c} %> cd /path/to/ASAACFT2000M-BS1_BOOT %> tar xvf gcc-linaro-6.1.1-2016.08-x86_64_aarch64-linux-gnu.tar.xz %> ./run build u-boot %\end{minted} %生成的 bootloader 文件是: \texttt{image/A/bootloader.bin} 。