Sipeed矽速科技
直播中

范嘉琦

6年用户 76经验值
擅长:可编程逻辑 嵌入式技术
私信 关注

【LicheeRV-Nano开发套件试用体验】基础开发环境

一、开发环境分类

注意,虽然是开发程序,但是这块处理器涉及到TPU,且官方的基本环境以及教程没出完,导致这块处理器的开发SDK其实是分化的。分为常规APP开发以及TPU开发。开发TPU可以兼容APP。

其次,这颗处理器刨开RiscV和ARM V53的二选一。它还包含一个700Mhz的大MUC核,一个8051的小MCU小核。

但是很不幸,相比于CV1800B,这颗处理器的协同核开发SDK还没制作完毕。它的freertos大核毫无资料。小核8051也只给了个JTAG接口,甚至和主核的通信资料都没给出。

更离谱的事很多时候它的资料仍然和CV18XX的资料共用。导致很多库和资源现在根本对不上。

二、开发个简单APP

首先官方给出了基本APP的sdk,那就是host-tools。

但是,你查过它的例程才会知道,它默认编译选项用的库版本不对!你需要特意选择你对应的核版本。因此你的CFLAGS和CXXFLAGS(注意,大部分库都会同时识别CXXFLAGS和CPPFLAGS,但是个别奇葩库只认CPPFLAGS)

CFLAGS="-mcpu=c906fdv -march=rv64imafdcv0p7xthead -mcmodel=medany -mabi=lp64d"

CFLAGS和CXXFLAGS在这部分的设置是完全一样的。

根据我现在编译的库。大部分库和2024/03/17时候各官方库公布的最新版本是一样的。下载时候记得看看版本公布时间。

官方默认固件使用的gcc host版本为riscv64-unknown-linux-musl

对于部分不认基础环境变量的库,和需要双编译的库需要特殊处理。但是大部分库使用下面代码可以安全编译过去

export TOOLCHAIN=/home/host-tools/gcc/riscv64-linux-musl-x86_64/bin PREFIX=/home/host-tools/gcc/riscv64-linux-musl-x86_64/sysroot/usr TARGET=riscv64-unknown-linux-musl CC=TOOLCHAIN/riscv64-unknown-linux-musl-gcc CXX=TOOLCHAIN/riscv64-unknown-linux-musl-g++ NM=TOOLCHAIN/riscv64-unknown-linux-musl-nm RANLIB=TOOLCHAIN/riscv64-unknown-linux-musl-ranlib LD=TOOLCHAIN/riscv64-unknown-linux-musl-ld AR=TOOLCHAIN/riscv64-unknown-linux-musl-ar STRIP=TOOLCHAIN/riscv64-unknown-linux-musl-strip CPATH=PREFIX/include LIBRARY_PATH=PREFIX/lib CFLAGS="-fPIC --sysroot=PREFIX/../ -mcpu=c906fdv -march=rv64imafdcv0p7xthead -mcmodel=medany -mabi=lp64d" CXXFLAGS="-fPIC --sysroot=PREFIX/../ -mcpu=c906fdv -march=rv64imafdcv0p7xthead -mcmodel=medany -mabi=lp64d" CPPFLAGS="-fPIC --sysroot=PREFIX/../ -mcpu=c906fdv -march=rv64imafdcv0p7xthead -mcmodel=medany -mabi=lp64d" LDFLAGS="-LPREFIX/lib -Wl,-rpath-link=PREFIX/lib -mcpu=c906fdv -march=rv64imafdcv0p7xthead -mcmodel=medany -mabi=lp64d" SYSROOT=$PREFIX/../ MAKEFLAGS="-j24"

自己的环境需要做如下改动:

首先TOOLCHAIN是你的编译器基本地址,也就是编译器bin目录所在位置。

第二是PREFIX是你库安装位置。官方给做了sysroot,你直接加紧sysroot按照标准隔离环境做就行。没必要强行分。到时候多版本编译它会自动加入版本尾号的so文件。这是linux应对多版本的一个方法,可以自行查询。

对于MAKEFLAGS来说就是你编译代码用几个线程。和make -j n-j n的作用一样。根据电脑性能自己改。

其他变量都是根据TOOLCHAINPREFIX生成出来的。但是也要注意,因为第一次运行这俩变量其实不存在。因此想要完整加载这些变量,需要将这个export的代码 在bash中连续运行2次

本人是在docker中进行的编译。因此清除这些变量最好的办法就是直接退出docker命令行重新进入。对于真机编译的勇士,或者没有条件使用隔离环境的同志。这些设置的所有变量系统默认都是空的。因此对上卖弄每一个设置的环境变量进行unset NAME就能清空这些环境变量。

比如说:

json-c 0.17

glib 2.80.0

由于几乎系统除了json-c库,其实几乎只提供了std库和libc库,所以大部分款本自己开心就好了。

注意,系统镜像额外提供了glib。但是和2.80能兼容

对于绝大多数情况,这点库文件消耗内存不足一提。因此加载自己的独立库系统也可以。但是记住别一个APP加载一套。因为这个处理器的内存实在是太捉襟见肘了。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>

#include <glib-2.0/glib.h>
#include <linux/gpio.h>

#define LOG_TAG "main"

#include <elog.h>

#include <json-c/json.h>

#include "IdHelper.h"

gboolean callback(gpointer argv){
    log_i("run a task");
    return true;
}

int main(int argc, char* argv[]){
//    setbuf(stdout, NULL);
    elog_init();
    elog_set_fmt(ELOG_LVL_ASSERT, ELOG_FMT_ALL);
    elog_set_fmt(ELOG_LVL_ERROR, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
    elog_set_fmt(ELOG_LVL_WARN, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
    elog_set_fmt(ELOG_LVL_INFO, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
    elog_set_fmt(ELOG_LVL_DEBUG, ELOG_FMT_ALL & ~ELOG_FMT_FUNC);
    elog_set_fmt(ELOG_LVL_VERBOSE, ELOG_FMT_ALL & ~ELOG_FMT_FUNC);
    elog_set_text_color_enabled(true);
    elog_start();


    g_print("Hello World glib!\n");

    log_a("Hello EasyLogger Assert!");
    log_e("Hello EasyLogger Error!");
    log_w("Hello EasyLogger Warning!");
    log_i("Hello EasyLogger Info!");
    log_d("Hello EasyLogger Debug!");
    log_v("Hello EasyLogger Verbose!");
//        elog_raw("Hello EasyLogger!");

    // 必须检查g_thread是否能用。否则将无法进入main_loop。新版本glib自动做了这部分呢
    //if (g_thread_supported() == 0){
    //    g_thread_init(NULL);
    //}else{
    //    return EXIT_FAILURE;
    //} // if g_thread_supported

    GMainLoop* loop = g_main_loop_new(NULL, false);

    g_timeout_add(1000, callback, NULL);

    g_main_loop_run(loop);

    GString* test_str = g_string_new("test glib string\n");
    g_string_append(test_str, "test append str\n");
    g_print("test g_print: %s\n", test_str->str);
    g_string_free(test_str, true);

    GString* str = Get_Id_64();
    g_print("create2 nanoid: %s\n", str->str);
    g_print("list size: %04ld\n", Get_64_list_size());
    Clear_64_list();
    g_print("list size: %04ld\n", Get_64_list_size());
  
  for (int index=0; index<1; index++) {
  	struct json_object *obj = json_object_new_object();
    json_object_object_add(obj, "name", json_object_new_string("xiaoming"));
    json_object_object_add(obj, "age", json_object_new_int(20));
    log_d(json_object_to_json_string(obj));
    json_object_put(obj);
    sleep(1);
  }
    g_main_loop_unref(loop);
    return EXIT_SUCCESS;
}

上面示例代码太简单了。如果真有零基础的,有问题直接问。留言私信都行!偶尔没看到每次来耍测评区的时候绝对会看到!。我的其他测评部分也能看到这部分讲解。

上面用到的库是easyLogger。直接去github搜就能搜到这个库,挺完善维护挺久的一个库。找最大的那个基本上不会被迷惑。

本项目我使用cmake做的。如果想用makefile也没问题。甚至因为涉及到你之前编译过glib,你直接用meson也可以。不过这个系统谷歌私有,用起来确实麻烦,效果大部分系统没感觉像宣传的那么简单。好多环境变量设置做的还不够完善,尤其是对交叉编译不太友好,因为谷歌给他用在了通用组件编译上。其交叉编译系统就像是个补丁一样贴在上面。

更多回帖

发帖
×
20
完善资料,
赚取积分