1. 程式人生 > >AliOS-Things--EMW3060--nano--新增一個新模組

AliOS-Things--EMW3060--nano--新增一個新模組

https://github.com/alibaba/AliOS-Things/wiki/Add-a-new-component-example.zh

一、新增一個元件:info_a

架構簡介

|----AliOS-Things
     |----example
     |      |----nano  # example目錄下的工程檔案將會被編譯執行,它將呼叫info_a元件
     |      |      |----nano.c
     |      |      |----nano.h
     |      |      |----nano.mk
     |
|...... |----framwork |----info_a # framwork目錄下的新元件,有.mk檔案 | |----info_a.c | |----info_a.h | |----info_a.mk |......

nano例程是最簡單的工程:它的路徑在AliOS-Things\example\nano\nano.c

/*
 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
 */
#include <stdio.h> #include <aos/aos.h> static void app_delayed_action(void *arg) { printf("nano %s:%d %s\r\n", __func__, __LINE__, aos_task_name()); } int application_start(int argc, char *argv[]) { do { app_delayed_action(NULL); aos_msleep(1000); }while(
1); }

 增加一個新模組供現有的app呼叫,執行檢視結果。 nano是aos自帶的一個最簡單的app例子,它實現了最簡單的延時迴圈列印功能,我們用它來作為例子中所用的app。 新增模組名設為 info_a,功能是列印一條特定的資訊。

在framework下建立一個 info_a 目錄

1.增加新模組原始檔

在 info_a 目錄中建立 info_a.c :

/*
 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
 */

#include <stdio.h>

void info_a_fun()
{
	printf("this is in info_a\n");
}

2.增加新模組的對外標頭檔案

在 info_a 目錄中建立 info_a.h :

/*
 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
 */

#ifndef INFO_A_H
#define INFO_A_H

#ifdef __cplusplus
extern "C" {
#endif

extern void info_a_fun();

#ifdef __cplusplus
}
#endif

#endif  /* INFO_A_H */

3.增加新模組的.mk檔案

.mk檔案是模組存在的標誌。每一個模組都會有一個對應的mk檔案,makefile通過搜尋mk字尾的檔案來查詢模組。其中聲明瞭一些針對該模組的定製化的東西。最基本的兩個就是該模組所包含的原始檔,標頭檔案路徑和該模組依賴的其他模組。
在info_a目錄下建立 info_a.mk:

NAME := info_a
$(NAME)_SOURCES := info_a.c
GLOBAL_INCLUDES += .

4.修改 nano 原始檔呼叫新介面

如:

/*
 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
 */

#include <stdio.h>
#include <aos/aos.h>
#include "info_a.h"

static void app_delayed_action(void *arg)
{
    printf("%s:%d %s\r\n", __func__, __LINE__, aos_task_name());
    info_a_fun();	
}

int application_start(int argc, char *argv[])
{
    do
    {
        app_delayed_action(NULL);
        aos_msleep(10);
    }while(1);
}

5. 修改 nano的 .mk 檔案依賴新模組

在nano.mk中新增一行:

$(NAME)_COMPONENTS += info_a

坑一:找不到標頭檔案

example/nano/nano.c:7:10: fatal error: info_a.h: No such file or directory
 #include <info_a.h>
          ^~~~~~~~~~

那好,我改:
我把#include <info_a.h>改成#include <../framework/info_a/info_a.h>標頭檔案,直接通過絕對目錄來指定標頭檔案的地方。嘚,沒報錯了,說明這是可以解決的。
不過又出現了新的問題:

out/[email protected]/libraries/nano.a(nano.o): In function `app_delayed_action':
D:\Output\AliOS\AliOS-Things/example/nano/nano.c:12: undefined reference to `info_a_fun'

函式info_a_fun沒有找到?抱歉,標頭檔案都沒報錯了,標頭檔案裡面有的函式你居然說找不到!再仔細找!
靠!!!nano.mk裡面寫錯了!
原有的沒改的,按照文件,我要在裡面新增一句:$(NAME)_COMPONENTS += info_a

NAME := nano

$(NAME)_SOURCES := nano.c


GLOBAL_DEFINES += AOS_NO_WIFI CONFIG_NO_TCPIP

mesh ?= 0

ifeq ($(BENCHMARKS),1)
$(NAME)_COMPONENTS  += benchmarks
GLOBAL_DEFINES      += CONFIG_CMD_BENCHMARKS
endif

然後,我就改成了以下這種錯誤的了!

NAME := nano

$(NAME)_SOURCES := nano.c


GLOBAL_DEFINES += AOS_NO_WIFI CONFIG_NO_TCPIP

mesh ?= 0

ifeq ($(BENCHMARKS),1)
$(NAME)_COMPONENTS  += benchmarks \ 
                       info_a                        # 注意不能在這裡加啊!!
GLOBAL_DEFINES      += CONFIG_CMD_BENCHMARKS
endif

正確的mk

NAME := nano

$(NAME)_SOURCES := nano.c
$(NAME)_COMPONENTS += info_a      # 正確的做法是要在這新增啊!

GLOBAL_DEFINES += AOS_NO_WIFI CONFIG_NO_TCPIP

mesh ?= 0

ifeq ($(BENCHMARKS),1)
$(NAME)_COMPONENTS  += benchmarks
GLOBAL_DEFINES      += CONFIG_CMD_BENCHMARKS
endif
  • 再編譯,我的標頭檔案還是這麼寫的#include <../framework/info_a/info_a.h>,編譯通過!
  • 那我改改標頭檔案#include <info_a/info_a.h>,編譯失敗!
  • 再改檔案#include <info_a.h>,編譯成功!

新增一個新模組的總結

1、新模組的C檔案、H檔案、mk檔案缺一不可!
2、呼叫模組時,工程裡面的mk檔案一定要新增模組那啥!$(NAME)_COMPONENTS += info_a
3、標頭檔案的包含方式就兩種:
(1)絕對路徑:#include <../framework/info_a/info_a.h>
(2)單獨標頭檔案:#include <info_a.h>

二、再新增一個元件:info_b

架構簡介

|----AliOS-Things
     |----example
     |      |----nano  # example目錄下的工程檔案將會被編譯執行,它將呼叫info_a、info_b元件
     |      |      |----nano.c
     |      |      |----nano.h
     |      |      |----nano.mk
     |      |......
     |----framwork
           |----info_a  # framwork目錄下的新元件a,有.mk檔案
           |      |----info_a.c
           |      |----info_a.h
           |      |----info_a.mk # 通過在這裡面新增關係,來帶出info_b元件
           |----info_b  # framwork目錄下的新元件b,有.mk檔案
           |      |----info_b.c
           |      |----info_b.h
           |      |----info_b.mk
           |......

使用同樣的方法新增一個info_b資料夾

  • info_b.c
  • info_b.h
  • info_b.mk

info_b.c

/*
 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
 */

#include <stdio.h>

void info_b_fun()
{
	printf("this is in info_b\n");
}

info_b.h

/*
 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
 */

#ifndef INFO_B_H
#define INFO_B_H

#ifdef __cplusplus
extern "C" {
#endif

extern void info_b_fun();

#ifdef __cplusplus
}
#endif

#endif  /* INFO_A_H */

info_b.mk

NAME := info_b
$(NAME)_SOURCES := info_b.c

GLOBAL_INCLUDES += .

好的,新元件b又做好了。
現在想讓元件b“依附”在元件a上面,即,nano工程只需要#include "info_a.h"就可以呼叫元件b的info_b_fun()函式。只需要在info_a.mk裡面寫:

NAME := info_a
$(NAME)_SOURCES := info_a.c
$(NAME)_COMPONENTS += info_b   # 新增這個依賴就可以了
GLOBAL_INCLUDES += .

如下就可以編譯了

/*
 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
 */

#include <stdio.h>
#include <aos/aos.h>
#include <info_a.h>    // 沒有info_b.h的標頭檔案

static void app_delayed_action(void *arg)
{
    printf("nano %s:%d %s\r\n", __func__, __LINE__, aos_task_name());
    info_b_fun();	  // 卻可以呼叫info_b裡面的元件
}

int application_start(int argc, char *argv[])
{
    do
    {
        app_delayed_action(NULL);
        aos_msleep(1000);
    }while(1);
}

三、再再新增一個元件:info_c/info_c_a

架構簡介

|----AliOS-Things
     |----example
     |      |----nano  # example目錄下的工程檔案將會被編譯執行,它將呼叫info_a、info_b元件
     |      |      |----nano.c
     |      |      |----nano.h
     |      |      |----nano.mk
     |      |......
     |----framwork
           |----info_a  # framwork目錄下的新元件a,有.mk檔案
           |      |----info_a.c
           |      |----info_a.h
           |      |----info_a.mk # 通過在這裡面新增關係,來帶出info_b元件
           |----info_b  # framwork目錄下的新元件b,有.mk檔案
           |      |----info_b.c
           |      |----info_b.h
           |      |----info_b.mk
           |----info_c # 該目錄中沒有.mk檔案,它的子目錄中有.mk檔案(加了一層)
           |      |----info_c_a
           |      |     |----info_c_a.c
           |      |     |----info_c_a.h
           |      |     |----info_c_a.mk
           |      |----info_c_b # 更多的新元件
           |      |.......
           |......

檔案還是老三樣(寫法和元件a的幾乎一模一樣就是,名字加了"_c"):

  • info_c_a.c
  • info_c_a.h
  • info_c_a.mk

就是元件在其他目錄之下,那麼在nano工程中該怎麼呼叫呢?

首先nano.mk得這麼寫:

NAME := nano

$(NAME)_SOURCES := nano.c

$(NAME)_COMPONENTS += info_c/info_c_a  # info_c裡面沒有.mk檔案所以....

GLOBAL_DEFINES += AOS_NO_WIFI CONFIG_NO_TCPIP

mesh ?= 0

ifeq ($(BENCHMARKS),1)
$(NAME)_COMPONENTS  += benchmarks
GLOBAL_DEFINES      += CONFIG_CMD_BENCHMARKS
endif

然後,nano.c裡面include標頭檔案就可以直接使用了

/*
 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
 */

#include <stdio.h>
#include <aos/aos.h>
#include <info_c_a.h>  // 新元件c的標頭檔案

static void app_delayed_action(void *arg)
{
    printf("nano %s:%d %s\r\n", __func__, __LINE__, aos_task_name());
    info_c_a_fun();	// 新元件c裡面的函式
}

int application_start(int argc, char *argv[])
{
    do
    {
        app_delayed_action(NULL);
        aos_msleep(1000);
    }while(1);
}

四、總結

 把這幾種型別的元件全部試用一次,就可以大致瞭解到AliOS-Things的檔案依賴與呼叫,包括.mk檔案的寫法就沒那麼迷糊了,還有就是大型的C工程裡面包含標頭檔案的寫法也是頭痛,經過以上的實驗之後,好像有那麼點清楚了。