天天看點

【LTE CAT1】ML302 OpenCPU | 應用開發入門一、新增源檔案二、應用程式的調用

一、新增源檔案

1. 增加源檔案

  1. sdk_root/src

    目錄下建立檔案夾

    user

    ,并建立源檔案

    user_app.c

/*********************************************************
*  @file    user_app.c
*  @brief   User application Entry File
*  Copyright (c) 2021 羽墨志.
*  All rights reserved.
*  created by 羽墨志 2021/04/02
********************************************************/
#include "user_app.h"

int user_app_main(void)
{
    cm_printf("hello world from [%s]\r\n", __func__);

    return 0;
}
           

【注】

[sdk_root]

為SDK的根目錄位置。

2. 在Makefile檔案中将新增的源檔案目錄添加到

SRC_DIRS

變量中,以空格與其他源檔案目錄分開;

SRC_DIRS := src src\demo\ssl src\user
           

2. 增加頭檔案

  1. sdk_root/inc

    目錄下建立檔案夾

    user

    ,并建立頭檔案檔案

    user_app.h

/*********************************************************
*  @file    user_app.h
*  @brief   User application header file
*  Copyright (c) 2021 羽墨志 Ltd.
*  All rights reserved.
*  created by 羽墨志 2021/04/02
********************************************************/

#ifndef __USER_APP_H__
#define __USER_APP_H__

#include "cm_main.h"

int user_app_main(void);

#endif
           
  1. 在Makefile檔案中将新增的頭檔案目錄添加到

    INC

    變量中,以空格與其他頭檔案目錄分開;
INC :=  -I'inc\os' -I'inc\apb' -I'inc\lwip' -Isrc -I. -Iinc  -I'inc\cm'  -Iinc\mbedtls -Iinc\os\include -Iinc\cJSON -Iinc\os\include\sys -Iinc\user
           

3. 增加宏定義

為了保證新增的代碼不影響原有SDK的結構,在Makefile檔案中新增一個宏定義

USER_APP_SUPPORT

  1. [src_root]

    目錄下的

    cm_feature.mk

    的檔案中添加一行定義,用于控制是否新增宏定義:
#配置使用者自定功能,Add by GuoHua
cm_user_app_on = y
           
  1. [src_root]

    目錄下的

    Makefile

    檔案中根據變量的指派情況決定是否添加宏定義:
ifeq ($(cm_user_app_on),y)
CFLAGS += -DUSER_APP_SUPPORT
endif
           

當變量

cm_user_app_on

指派為

y

時,則添加宏定義

USER_APP_SUPPORT

,這樣就可以直接在應用程式中使用該宏定義了。

注意在Makefile中添加宏定義時不要忘記了前面的參數

-D

最後整理一下,将添加的源檔案以及頭檔案目錄的定義包含到這個判斷中來:

ifeq ($(cm_user_app_on),y)
CFLAGS += -DUSER_APP_SUPPORT
INC += -Iinc/user
SRC_DIRS += src/user
endif
           

這樣就可以在配合宏定義

GH_USER_APP_SUPPORT

在應用程式中的使用,并通過變量

cm_user_app_on

的指派來決定是否在SDK中添加使用者自定義的應用程式了。

二、應用程式的調用

1. 入口函數

ML302 OpenCPU的入口函數是

void ML302_OpenCPU_Entry()

,位于檔案

[sdk_root]/src/cm_main.c

中。該函數在模組主程式

main

函數中被調用,用于使用者應用線程的建立,是以不能阻塞該函數。

void ML302_OpenCPU_Entry()
{
#ifdef CM_DEMO_SUPPORT
    cm_test_alarm_init();
    cm_test_keypad_init();
    // 定義主線程
    osThreadDef(OC_Main_Task, cm_main_task, osPriorityNormal, 0, 8192);
    // 建立主線程
    OC_Main_TaskHandle = osThreadCreate(osThread(OC_Main_Task), 0);  

#ifdef CM_FOTA_SUPPORT   //啟用OneNet FOTA不可删除
    cm_onenet_fota_regcbex();
#endif
#endif
}
           

函數

void ML302_OpenCPU_Entry()

的工作是進行基本的初始化,定義并建立使用者APP主線程,

cm_main_task

為APP線程的回調函數,在該回調函數中完成應用程式的開發。

2. 程式調用

在檔案

[sdk_root]/src/cm_main.c

的适當位置添加如下代碼以便将使用者自定義的頭檔案包含進來:

#ifdef USER_APP_SUPPORT
#include "user_app.h"
#endif
           

在APP線程的回調函數

void cm_main_task(void *p)

中添加使用者自定義應用程式的主函數:

#ifdef USER_APP_SUPPORT
    user_app_main();
#endif
           

宏定義

USER_APP_SUPPORT

的開關由

[sdk_root/cm_feature.mk]

檔案中的控制變量

cm_user_app_on

來決定,這樣就可以通過

cm_user_app_on

來控制是否添加使用者自定義的應用程式了。修改後的APP線程的回調函數

void cm_main_task(void *p)

如下所示,主要是添加了

user_app_main();

函數和部分注釋:

void cm_main_task(void *p)
{  
   unsigned char buf[50] = {0};
   int i;
   struct l_tm t;
   cm_test_uart_init(); // 序列槽初始化
   cm_printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
   cm_printf("ML302 OpenCPU Starts\n");
   cm_printf("Boot Cause:%d\n",cm_sys_get_boot_cause());
   cm_sys_get_sdk_swver(buf,50); // 讀取SDK版本号
   cm_printf("SDK VERSION:%s\n",buf);
   cm_sys_get_base_swver(buf,50); // 讀取基線版本号
   cm_printf("BASELINE VERSION:%s\n",buf);
   cm_sys_get_hwver(buf,50); // 讀取硬體版本号
   cm_printf("HW VERSION:%s-%s\n",buf,CM_HARDWARE_VERSION);  
   cm_printf("waiting for network...\n");
   cm_test_vir_at_init(); // 虛拟AT初始化
   cm_test_network_config(); // 網絡初始化配置
   time_to_date(osiEpochSecond()+cm_get_timezone()* 15*60,&t); // 擷取目前時間
   cm_printf("Now:%d-%d-%d:%d:%d:%d\n",t.tm_year,t.tm_mon+1,t.tm_mday,t.tm_hour,t.tm_min,t.tm_sec);
   osDelay(1000);
   cm_test_get_imei(); // 讀取IMEI
   cm_test_get_imsi(); // 讀取IMSI
   cm_test_get_iccid(); // 讀取ICCID
   #ifdef CM_FOTA_SUPPORT  
   char *version = NULL;
   onVersion(&version); // 讀取OneNet FOTA版本号
   cm_printf("OneNet FOTA version:%s\n", version);
   #endif

#ifdef USER_APP_SUPPORT
    user_app_main(); // 使用者應用程式主函數
#endif
    
#ifdef CM_SPIFLASH_FS_SUPPORT
    cm_fsMountSpiFlash();
#endif       
    while(1) // 循環等待序列槽輸入
    {
        cm_printf("\nplease input cmds:\n");
        osSignalWait(0x0004, osWaitForever);

        if((cmd_len < 2))
        {
            cm_printf("CMD NOT DEFINE\n");    
        }
        else
        {
            for(i = 0;i< (sizeof(cmd_vector)/sizeof(cm_cmd_t));i++)
            {                
                if(strcmp(cmd_buf[1],cmd_vector[i].cmdstr) == 0) // 依次尋找是否有比對的功能
                {
                    (*(cmd_vector[i].cmdfunc))(cmd_buf,cmd_len); // 按照接收到的參數執行相應的功能
                    cm_printf("OK\n");
                    break;
                }
            }
            if( i >=  (sizeof(cmd_vector)/sizeof(cm_cmd_t)))
            {
                cm_printf("CMD NOT DEFINE\n");
            }
        }
		for(i=0;i<cmd_len;i++)
        {
            free(cmd_buf[i]); // 依次釋放用于解析指令的序列槽緩沖區
        }	
        osMutexRelease( cmd_mutex ); // 釋放互斥鎖
    }
}
           

3. 結果驗證

按照《【LTE CAT1】ML302 OpenCPU | 開發環境搭建及固件更新》中提到的方法編譯程式并下載下傳固件到模組中,重新上電後可看到如下序列槽資訊:

【LTE CAT1】ML302 OpenCPU | 應用開發入門一、新增源檔案二、應用程式的調用

說明應用程式已成功調用。

繼續閱讀