0 Preface
MT7628K integrates multi-port ethernet switch, but in our Smart Plug project, we don't use it, we only use apcli function.
switch driver: ra305x_drivers/eth_ra305x/if_ra305x.c
1 Build
1.1 eCos编译
1)
apt-get install dos2unix
tar -jxvf 2016_0905_eCos_SDK_V3.1.4.0_DPA.tar.bz2
https://github.com/icplus/mtk7628_eCos
2)
cd eCos_SDK
make clean; make
3)
eCos.img is produced in the “ra305x_ap_adv/ra305x_router”directory
4)
make module_clean; make module
1.2 eCos make menuconfig
执行make menuconfig时会产生一个ra305x_ap_adv/ra305x_router/include/autoconf.h文件,由于很多用户一般不会用make menuconfig来做配置,那么可以直接修改该文件添加需要的模块。
1.3 APP自定义一个目录
in ra305x_ap_adv/ra305x_router/oem_iot
包含include、Makefile、src
in ra305x_ap_adv/ra305x_router/Makefile
[…]
# oem-begin
APPSUBDIRS += oem_iot
# oem-end
[…]
2 eCos APP自定义section
1)
in ra305x_ap_adv/ra305x_router/arch/mips/target.ld
in ra305x_ap_adv/ra305x_router/target.ld
SECTIONS
{
[...]
.text ALIGN (0x4) :
{
[...]
. = ALIGN(4);
PROVIDE (__core_initcall = .);
KEEP(*(.core.initcall))
PROVIDE (__core_initcall_end = .);
. = ALIGN(4);
PROVIDE (__module_initcall = .);
KEEP(*(.module.initcall))
PROVIDE (__module_initcall_end = .);
. = ALIGN(4);
PROVIDE (__late_initcall = .);
KEEP(*(.late.initcall))
PROVIDE (__late_initcall_end = .);
[...]
} > ram =0
[...]
}
2)
in ra305x_ap_adv/ra305x_router/oem_iot/include/oem_portmisc.h
[…]
typedef void (*initcall_t)(void);
extern initcall_t __core_initcall[];
extern initcall_t __core_initcall_end[];
extern initcall_t __module_initcall[];
extern initcall_t __module_initcall_end[];
extern initcall_t __late_initcall[];
extern initcall_t __late_initcall_end[];
#if 1
#define core_initcall(fn) \
static initcall_t __initcall_##fn \
__attribute__((used,section(".core.initcall"))) = fn
#define module_init(fn) \
static initcall_t __initcall_##fn \
__attribute__((used,section(".module.initcall"))) = fn
#define late_initcall(fn) \
static initcall_t __initcall_##fn \
__attribute__((used,section(".late.initcall"))) = fn
#else
#define core_initcall(fn) \
void fn(void) __attribute__((unused))
#define module_init(fn) \
void fn(void) __attribute__((unused))
#define late_initcall(fn) \
void fn(void) __attribute__((unused))
#endif
[…]
3)
in ra305x_ap_adv/ra305x_router/init/main.c
/* oem-begin */
#include "../oem_iot/include/oem_portmisc.h"
/* oem-end */
static void section_core_init(void)
{
initcall_t *initcall;
for (initcall = __core_initcall;
initcall < __core_initcall_end;
initcall++) {
(*initcall)();
}
}
static void section_module_init(void)
{
initcall_t *initcall;
for (initcall = __module_initcall;
initcall < __module_initcall_end;
initcall++) {
(*initcall)();
}
}
static void section_late_init(void)
{
initcall_t *initcall;
for (initcall = __late_initcall;
initcall < __late_initcall_end;
initcall++) {
(*initcall)();
}
}
3 eCos标准驱动框架
1)驱动路径
in packages/devs/serial/mips/vrc437x
2)修改ecos.db,将驱动编译进静态库
in packages/ecos.db
package CYGPKG_IO_SERIAL_MIPS_VRC437X {
alias { "VRC437X serial device drivers"
devs_serial_mips_vrc437x
vrc437x_serial_driver }
hardware
directory devs/serial/mips/vrc437x
script ser_mips_vrc437x.cdl
description "VRC437X serial device drivers"
}
3)中断处理头文件
#include <cyg/hal/hal_intr.h>
#include <cyg/hal/drv_api.h>
4 eCos API
4.1 线程同步
Mailbox(cyg_mbox_create)
Mailbox的结构是一个FIFO类型的循环队列,存储的是指针。
4.2 CFG API
static void api_usage_test(void)
{
cyg_uint64 c_time;
char line[8];
unsigned long tv_sec, tv_usec;
c_time = cyg_current_time();
tv_sec = (u_long)(c_time/100);
tv_usec = (((u_long)ctime)%100) * 10000;
diag_printf("tv_sec: %ld, tv_usec: %ld\n",
tv_sec, tv_usec);
// interface_config();
CFG_get_str(CFG_SYS_OPMODE, line);
diag_printf("opmode: %d\n",
strtol(line, NULL, 10));
CFG_reset_default();
//mon_snd_cmd(MON_CMD_REBOOT);
}
4.3 打印UTC时间
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
// time_t gmt_translate2localtime(time_t gmt_time)
// struct tm *gmtime(const time_t *timep)
/* 将时间结构体struct tm的值转化为经过的秒数 */
// time_t mktime(struct tm *tm)
/* translate " DD-mth-YY HH:MM:SS GMT" to elapsed seconds */
// time_t tdate_parse( char* str)
API void get_now_time(void)
{
struct timespec time;
struct tm nowtime;
//获取相对于1970到现在的秒数
clock_gettime(CLOCK_REALTIME, &time);
localtime_r(&time.tv_sec, &nowtime);
diag_printf(
"%04d%02d%02d%02d:%02d:%02d\n",
nowtime.tm_year + 1900,
nowtime.tm_mon + 1,
nowtime.tm_mday,
nowtime.tm_hour,
nowtime.tm_min,
nowtime.tm_sec);
}
5 eCos写MAC地址
ra0的MAC是读取0x0004、0x0006和0x0008三个寄存器。
假设MAC地址:00:0C:43:76:20:58
用USB2UART线进入eCos命令行后。
cd net
iwpriv ra0 e2p 04=0C00
iwpriv ra0 e2p 06=7643
iwpriv ra0 e2p 08=5820