天线电磁辐射

最近在搞射频方面的工作,发现普通RFID读头RF的输出功率最高可达到32.5dBm(1.7W),天线增益假如是6dBi,线路损耗为2dBm的话,最终天线表面的等效辐射功率达32.5+6-2=36.5dBm(等效功率接近4W-_-!!!,这个功率就比较危险了,国标是33dBm和功率密度2W/平方米),也就是说要达到国标RF的最大输出功率要设置33-9+1=25dBm才可以,为安全其间尽量设小点:)。

说几点想到的:

  1. 就算不考虑天线也有最高也有1.7W,这个相比普通路由器的几个毫瓦高了1000倍。
  2. 尽量离天线越远越好。
  3. 不知生活中各种电磁辐射(手机、无线路由、电脑等等)对人体的影响,看到美国FCC的相关电磁对人体的报告,但没细看。
  4. 想起之前看新闻看到美国有些人患有电磁辐射过敏,没办法只能住在山洞里-_-!!!。
  5. 看了电磁炉其实也是用电磁感应加热金属,只不过大部分能量被金属吸收变成了热能,如果质量不好的话对周围的辐射也比较大吧。

最近睡眠不足,早点睡觉吧:(。

天线增益:http://baike.soso.com/v406959.htm

帮同事分析Makefile文件

同事想看开源项目contiki,无奈被其复杂的Makefile搞晕而找我帮忙。我大致看了一些,由于这个项目涉及到多个目标平台,结构复杂可想而知啦-_-!!!。这里用相对简单的原生平台(native)来剖析一下。

大致上有四个重要的Makefile文件:

  1. 自己的应用程序Makefile,如examples/email/Makefile:

    这个定义了最终的目标应用程序名,如email:

    CONTIKI_PROJECT = email-client
    all: $(CONTIKI_PROJECT)
    
    APPS = email
    
    CONTIKI = ../..
    include $(CONTIKI)/Makefile.include
    
  2. 根目录的Makefile.include:

    这个提供了统一的Makefile框架,提供一般的编译选项和功能,各个平台可以覆盖这些默认规则。

  3. platform/native/Makefile.native:

    这个是平台相关的硬件,如串口、led等,以及定义最终链接生成的目标文件%.$(Target)的编译规则。原生平台(native)直接在Makefile.include里定义了最终目标%.$(Target)的规则了。其他的平台要定义宏CUSTOM_RULE_LINK来进行覆盖。

  4. cpu/native/Makefile.native

    这个定义目标文件和库的编译。如果这里不是native平台,要定义自己的链接和编译规则,要预先定义几个宏覆盖系统默认的规则:

    CUSTOM_RULE_LINK=1
    CUSTOM_RULE_C_TO_OBJECTDIR_O=1
    CUSTOM_RULE_ALLOBJS_TO_TARGETLIB=1
    

    上面分别对应链接、编译和打包成库。编译和打包成库直接在这个Makefile里,最终的链接在platform//Makefile.里。

讲了这么多,来看一下最技巧性的地方。

CONTIKI_PROJECT = email-client
all: $(CONTIKI_PROJECT)

这里只指定了一个email-client,不带任何扩展名。那make如果知道依赖什么能?这里就要用到make的隐式规则了。

隐式规则

make看到email-client这个目标会采用两条隐式规则:

%:%.c
    gcc $(CFLAGS) %< -o $@

或者

# 这个会生成中间文件xxx.o,make会在完成时删除。
%:%.o
    gcc %< -o $@

%.o:%.c
    gcc $(CFLAGS) -c %< -o $@  

那如果要让make执行我预定义的依赖项:

# @ 表示占位符,如果没有则代表删除这条规则
%:%.$(TAGET)
    @

则要删除%:%.c这条隐式规则才能执行我的%:%.$(TAGET)。至于第二条隐式规则相比我的%:%.$(TAGET)要复杂,make是比较聪明的不回绕远路的。

删除%:%.c规则(不加命令项):

%:%.c

重看Makefile.include

有了上面的知识,下面就比较好理解了,最终的目标是email-client.native,链接规则是:

ifndef CUSTOM_RULE_LINK
%.$(TARGET): %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a
    $(LD) $(LDFLAGS) $(TARGET_STARTFILES) ${filter-out %.a,$^} ${filter %.a,$^} $(TARGET_LIBFILES) -o $@
endif

编译规则是:

ifndef CUSTOM_RULE_C_TO_OBJECTDIR_O
$(OBJECTDIR)/%.o: %.c
    $(CC) $(CFLAGS) -MMD -c $< -o $@
    @$(FINALIZE_DEPENDENCY)
endif

打包生产库规则:

ifndef CUSTOM_RULE_ALLOBJS_TO_TARGETLIB
contiki-$(TARGET).a: $(CONTIKI_OBJECTFILES)
    $(AR) $(AROPTS) $@ $^
endif

其他平台的类似,只是中间有很多步骤,这里不细讲。

Makefile自动产生依赖文件(二)

昨天写的Makefile自动产生依赖文件(一)是我以前用的方法总结,但近期发现了GCC本来就有这个功能,只是我没发现罢了-_-!!!。

这还说着摆弄Eclipse CDT开发环境时,无意中发现Eclipse产生的Makefile异常简洁,其核心的src/subdir.mk文件如下:

CPP_SRCS += 
../src/HelloWorld.cpp 

OBJS += 
./src/HelloWorld.o 

CPP_DEPS += 
./src/HelloWorld.d 

src/%.o: ../src/%.cpp
    @echo 'Building file: $<'
    @echo 'Invoking: Cygwin C++ Compiler'
    g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<"
    @echo 'Finished building: $<'
    @echo ' '

细看src/%.o: ../src/%.cpp的隐规则,发现多了几个参数”-MMD -MP -MF -MT”。”-MMD“我还认的,就是直接产生.d文件而不是输出到屏幕,其他就陌生了。遇到问题找Man啦,发现正好解决了我前一篇博客所说的两个问题,gcc果然不我欺也。

  • -MP: 解决重命名头文件导致的依赖破裂,跟上次的思路一样,生成了dummy目标。

  • -MF: 这个是指定输出的.d文件格式。

  • -MT: 这个解决了输出的目标文件不带路径问题,可以指定目标文件的格式。

现在可以抛弃之前的makedepend,一个Makefile文件搞定一切:)。


更新

今天发现头文件更新不起作用,看来一下.d文件如下:

xxx.d: xxx.h //这里应为xxx.o:xxx.h
xxx.h:

惊讶的发现竟然没有xxx.o的依赖,再仔细检查了gcc的依赖选项发现之前没仔细看-MT修改了依赖项变成了.d了。其实-MT不用加上,加上就修改了目标名,最后的命令是:

$(OBJS):%.o:%.c
    gcc -c $(CFLAGS) -MMD -MP -MF"$(@:%.o=%.d)" -o $@ $<

这里用到了makefile静态规则(要详细看那边《跟我一起学Makefile》),这样就保证文件名不会被gcc给截断造成依赖文件的目标名错误。

最后贴个标准的吧:

SRC_DIR= src others
CFLAGS+=-Wall -g 
CFLAGS+=$(addprefix -I, $(SRC_DIR))
CFILES=$(shell find $(SRC_DIR) -maxdepth 1 -name "*.c")
OBJS=$(CFILES:%.c=%.o)
LIBS+= 

all:$(TARGET)

-include $(addsuffix /*.d, $(SRC_DIR))

$(TARGET):$(OBJS)
    gcc $(LDFLAGS) $^ -o $@ $(LIBS)

$(OBJS):%.o:%.c
    gcc -c $(CFLAGS) -MMD -MP -MF"$(@:%.o=%.d)" -o $@ $<

clean:
    -rm -f $(addsuffix /*.d, $(SRC_DIR)) $(addsuffix /*.o, $(SRC_DIR)) $(TARGET)

Apache频频Crash

自从换到WordPress后Apache频频Crash,每次都得手动重启Apache(怀念以前小巧的Python博客)-_-!!!。最近比较忙也懒的理,我推测是VPS内存太小(512M),伺候不好MySQL和Apache这些大爷啊:)。前几天查看了下进程列表发现MySQL内存飙到150M了,实在忍无可忍便优化了一下MySQL,网上大致的意思是Innodb引擎耗内存,换用MyISAM。

修改/etc/mysql/my.cnf,在[mysql]里加入

default-storage-engin=MyISAM
loose-skip-innodb

注意MySQL5.5.18中skip-innodb已经改成loose-skip-innodb了。

重启MySQL,发现内存占用一直保持在50M内,效果还不错。顺便关闭了一些不要的服务(DNS等),如果Apache还Crash,那得优化Apache了-_-!!!。

参考

http://www.justwinit.cn/post/4785/

Makefile自动产生依赖文件(一)

一直以来用Makefile自动产生源文件(C/C++)的关联文件(.d)是一大问题。这里主要涉及到的是gcc的-MM选项(-M会包含系统头文件)。但gcc的-MM不是很完美,主要涉及到两方面:

  1. 没有目标文件路径

    g++ -MM src/string_parse.cpp
    

    输出:

    string_parse.o: src/string_parse.cpp src/string_parse.h
    

    而我们需要的是:

    src/string_parse.o: src/string_parse.cpp src/string_parse.h
    
  2. 头文件重命名时出现错误

    万一我们重命名了string_parse.h为string_other_parse.h则

    string_parse.o: src/string_parse.cpp src/string_other_parse.h
    

    make会找不到依赖文件str/string_other_parse.h报错。

参考网上的方案,我的解决方法是写个makedepend脚本处理:

#!/usr/bin/env bash
# Generate C/C++ file make depend file: Makefile.depends.
# Usage:
#   makedepend -f files -c (gcc|g++) -p flags

help() 
{
    echo "${0#*/} -f files -c (gcc|g++) -p flags"
}

while getopts "hf:c:p:" opt; do
    case $opt in
        h)
            help
            exit 0
            ;;
        f)
            files=$OPTARG
            ;;

        c)
            compiler=$OPTARG
            ;;

        p)
            flags=$OPTARG
            ;;
        *)
            exit 1
            ;;
    esac
done


if [ -z "$files" ] || [ -z "$compiler" ] || [ -z "$flags" ] ; then
    exit 1
fi

for file in $files
do
    obj="${file%.*}.o"
    result=`$compiler -MM $flags $file`
    if [ $? != 0 ] ; then
        exit 1
    fi

    result=${result/*:/$obj:}
    echo $result | sed -e 's/\//g'
    # add all file as target, so rename file will not error.
    echo $result | sed -e 's/.*://' -e 's/\//g' | fmt -1 | sed -e 's/^ *//' -e 's/$/:/'
done

在Makefile是这么用的:

Makefile.deps: $(FILES) $(HEADERS)
    makedepend -f "$(FILES)" -c "$(CXX)" -p "$(CPPFLAGS)" >$@

最后生成的Makefile.deps是这样的:

src/string_parse.o: src/string_parse.cpp src/string_parse.h
src/string_parse.cpp:
src/string_parse.h:

为了防止修改文件名后找不到,makedepend为每个依赖文件都建了一个空规则,make如果找不到文件,可以在这里找到。由于文件不存在,成为了伪目标,而伪目标永远是最新的,从而触发编译命令

参考:

陈皓的《跟我一起写Makefile》

Autodependencies with GNU make

http://blog.vjeux.com/category/makefile