5.Cross compile libiconv-1.13.1
$ CC=arm-none-linux-gnueabi-gcc AR=arm-none-linux-gnueabi-ar CXX=arm-none-linux-gnueabi-g++ ./configure --host=arm-linux --target=arm-linux --prefix=/opt/arm-2008q1/arm-none-linux-gnueabi/libc/usr --cache-file=/dev/null
$ make
$ sudo PATH=$PATH:/opt/arm-2008q1/bin make install
6.Cross compile libxml2-2.7.8
$ CC=arm-none-linux-gnueabi-gcc AR=arm-none-linux-gnueabi-ar CXX=arm-none-linux-gnueabi-g++ ./configure --host=arm-linux --target=arm-linux --prefix=/opt/arm-2008q1/arm-none-linux-gnueabi/libc/usr --cache-file=/dev/null
$ make
$ sudo PATH=$PATH:/opt/arm-2008q1/bin make install
7.Cross compile php-5.2.17
$ ac_cv_lib_mysqlclient_mysql_close=yes ac_cv_lib_mysqlclient_mysql_stmt_field_count=yes ac_cv_lib_mysqlclient_mysql_set_server_option=yes ac_cv_lib_mysqlclient_mysql_errno=yes ac_cv_func_iconv=yes CC=arm-none-linux-gnueabi-gcc AR=arm-none-linux-gnueabi-ar CXX=arm-none-linux-gnueabi-g++ ./configure --host=arm-linux --target=arm-linux --prefix=/home/gigijoe/BeagleBoard/rootfs/usr/local --disable-all --with-config-file-path=/rootfs/usr/local/etc --with-mysql=/home/gigijoe/BeagleBoard/rootfs/usr/local/mysql --with-mysqli=/home/gigijoe/BeagleBoard/rootfs/usr/local/mysql/bin/mysql_config --with-mysql-sock=/tmp/mysqld.sock --disable-rpath --enable-discard-path --enable-safe-mode --enable-shmop --enable-sysvsem --enable-inline-optimization --enable-fastcgi --enable-force-cgi-redirect --enable-embedded-mysqli --with-libxml-dir=/opt/arm-2008q1/arm-none-linux-gnueabi/libc/usr --cache-file=/dev/null
$ make
$ make install
8.Cross compile lighttpd-1.4.28
$ CFLAGS="-I/home/gigijoe/BeagleBoard/rootfs/usr/local/mysql/include" CC=arm-none-linux-gnueabi-gcc AR=arm-none-linux-gnueabi-ar CXX=arm-none-linux-gnueabi-g++ ./configure --host=arm-linux --target=arm-linux --prefix=/home/gigijoe/BeagleBoard/rootfs/usr/local --with-mysql=/home/gigijoe/BeagleBoard/rootfs/usr/local/mysql --without-pcre --without-bzip2 --disable-ipv6 --cache-file=/dev/null
$ make
$ make install
9.ARM Target setup
記的將以上相關安裝到/opt/arm-2008q1/arm-none-linux-gnueabi/libc/usr的libraries複製到ARM target.
指定library搜尋路徑
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib:/usr/local/mysql/lib
10.Reference
http://wiki.huihoo.com/index.php?title=FreeBSD_Lighttpd_PHP_MySQL
http://www.cmake.org/Wiki/CMake_Cross_Compiling
http://forge.mysql.com/wiki/Autotools_to_CMake_Transition_Guide
http://forge.mysql.com/wiki/CMake
http://redmine.lighttpd.net/wiki/1/TutorialConfiguration
http://www.memorybbs.com/cgi-bin/topic.cgi?forum=77&topic=92
2011年1月28日 星期五
Cross Compile Lighttpd + PHP + MySQL for ARM (1)
目標是要在ARM platform上跑HTTP Server並且支援PHP & MySQL.
HTTP server選擇lighttpd.整個cross comiple流程大致是先build MySQL,
因為PHP需要連結MySQL,再來是bulid PHP 最後才是lighttpd.
ARM cross compile 是 CodeSourcery 2008q1版本.
首先了解一下cross compile搜尋路徑
$ arm-none-linux-gnueabi-gcc -print-search-dirs
install: /opt/arm-2008q1/bin/../lib/gcc/arm-none-linux-gnueabi/4.2.3/
programs: =/opt/arm-2008q1/bin/../libexec/gcc/arm-none-linux-gnueabi/4.2.3/:/opt/arm-2008q1/bin/../libexec/gcc/:/opt/arm-2008q1/bin/../lib/gcc/arm-none-linux-gnueabi/4.2.3/../../../../arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi/4.2.3/:/opt/arm-2008q1/bin/../lib/gcc/arm-none-linux-gnueabi/4.2.3/../../../../arm-none-linux-gnueabi/bin/
libraries: =/opt/arm-2008q1/bin/../lib/gcc/arm-none-linux-gnueabi/4.2.3/:/opt/arm-2008q1/bin/../lib/gcc/:/opt/arm-2008q1/bin/../lib/gcc/arm-none-linux-gnueabi/4.2.3/../../../../arm-none-linux-gnueabi/lib/arm-none-linux-gnueabi/4.2.3/:/opt/arm-2008q1/bin/../lib/gcc/arm-none-linux-gnueabi/4.2.3/../../../../arm-none-linux-gnueabi/lib/:/opt/arm-2008q1/bin/../arm-none-linux-gnueabi/libc/lib/arm-none-linux-gnueabi/4.2.3/:/opt/arm-2008q1/bin/../arm-none-linux-gnueabi/libc/lib/:/opt/arm-2008q1/bin/../arm-none-linux-gnueabi/libc/usr/lib/arm-none-linux-gnueabi/4.2.3/:/opt/arm-2008q1/bin/../arm-none-linux-gnueabi/libc/usr/lib/
由以上libraries搜尋路徑偶選擇 /opt/arm-2008q1/arm-none-linux-gnueabi/libc/usr 作為相關所需libraries的安裝位置
1.Download & cross compile pcre-8.12 & ncurses-5.7
$ cd pcre-8.12/
$ CC=arm-none-linux-gnueabi-gcc AR=arm-none-linux-gnueabi-ar CXX=arm-none-linux-gnueabi-g++ ./configure --host=arm-linux --target=arm-linux --prefix=/opt/arm-2008q1/arm-none-linux-gnueabi/libc/usr --cache-file=/dev/null
$ make
$ sudo PATH=$PATH:/opt/arm-2008q1/bin make install
$ cd ../ncurses-5.7
$ CC=arm-none-linux-gnueabi-gcc AR=arm-none-linux-gnueabi-ar CXX=arm-none-linux-gnueabi-g++ ./configure --host=arm-linux --target=arm-linux --prefix=/opt/arm-2008q1/arm-none-linux-gnueabi/libc/usr --cache-file=/dev/null
$ make
$ sudo PATH=$PATH:/opt/arm-2008q1/bin make install
在make install 時加上PATH=$PATH:/opt/arm-2008q1/bin是為了在root權限下也能執行cross compiler.
2.Cross compile mysql-5.5.8
MySQL在5.5之後不在使用autoconf系統而採cmake.
建立 toolchain.cmake 內容如下
# this one is important
SET(CMAKE_SYSTEM_NAME Linux)
#this one not so much
SET(CMAKE_SYSTEM_VERSION 1)
# specify the cross compiler
SET(CMAKE_C_COMPILER /opt/arm-2008q1/bin/arm-none-linux-gnueabi-gcc)
SET(CMAKE_CXX_COMPILER /opt/arm-2008q1/bin/arm-none-linux-gnueabi-g++)
SET(CMAKE_STRIP /opt/arm-2008q1/bin/arm-none-linux-gnueabi-strip)
# where is the target environment
SET(CMAKE_FIND_ROOT_PATH /opt/arm-2008q1/arm-none-linux-gnueabi/libc)
# search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
接著執行cmake
$ cmake -DCMAKE_TOOLCHAIN_FILE=./toolchain.cmake -DMYSQL_DATADIR=/var/lib/mysql/data -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DEXTRA_CHARSETS=all -DMYSQL_UNIX_ADDR=/tmp/mysqld.sock -DMYSQL_TCP_PORT=3306 -DENABLED_LOCAL_INFILE=1 -DWITH_PARTITION_STORAGE_ENGINE=1 -DWITH_INNOBASE_STORAGE_ENGINE=1 -DMYSQL_USER=mysql -DCMAKE_INSTALL_PREFIX=/home/gigijoe/BeagleBoard/rootfs/usr/local/mysql -DWITH_EMBEDDED_SERVER=1 -DCMAKE_C_COMPILER=arm-none-linux-gnueabi-gcc -DCMAKE_CXX_COMPILER=arm-none-linux-gnueabi-g++ -DSTACK_DIRECTION=1
$ make VERBOSE=1
出現錯誤
[ 2%] Building C object cmd-line-utils/libedit/CMakeFiles/edit.dir/term.c.o
cd /home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit && /opt/arm-2008q1/bin/arm-none-linux-gnueabi-gcc -DHAVE_CONFIG_H -Wall -O2 -g -DDBUG_OFF -I/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit -I/home/gigijoe/BeagleBoard/mysql-5.5.8/include -o CMakeFiles/edit.dir/term.c.o -c /home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c:59:20: error: curses.h: No such file or directory
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c: In function 'term_set':
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c:928: warning: implicit declaration of function 'tgetent'
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c:946: warning: implicit declaration of function 'tgetflag'
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c:955: warning: implicit declaration of function 'tgetnum'
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c:959: warning: implicit declaration of function 'tgetstr'
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c:960: warning: passing argument 3 of 'term_alloc' makes pointer from integer without a cast
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c: In function 'term_tputs':
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c:1261: warning: implicit declaration of function 'tputs'
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c: In function 'term_echotc':
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c:1560: warning: assignment makes pointer from integer without a cast
make[2]: *** [cmd-line-utils/libedit/CMakeFiles/edit.dir/term.c.o] Error 1
make[2]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make[1]: *** [cmd-line-utils/libedit/CMakeFiles/edit.dir/all] Error 2
make[1]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make: *** [all] Error 2
修改 /home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c
#ifdef HAVE_CURSES_H
-#include
+#include
#endif
#ifdef HAVE_NCURSES_H
-#include
+#include
#endif
/* Don't use Solaris's term.h. */
#if (defined(HAVE_TERM_H) && !defined(__SunOS))
-#include
+#include
#endif
再次嘗試
$ make VERBOSE=1
出現錯誤
[ 28%] Generating ../include/mysqld_error.h, ../sql/share/english/errmsg.sys
cd /home/gigijoe/BeagleBoard/mysql-5.5.8/extra && ./comp_err --charset=/home/gigijoe/BeagleBoard/mysql-5.5.8/sql/share/charsets --out-dir=/home/gigijoe/BeagleBoard/mysql-5.5.8/sql/share/ --header_file=/home/gigijoe/BeagleBoard/mysql-5.5.8/include/mysqld_error.h --name_file=/home/gigijoe/BeagleBoard/mysql-5.5.8/include/mysqld_ername.h --state_file=/home/gigijoe/BeagleBoard/mysql-5.5.8/include/sql_state.h --in_file=/home/gigijoe/BeagleBoard/mysql-5.5.8/sql/share/errmsg-utf8.txt
./comp_err: 1: Syntax error: word unexpected (expecting ")")
make[2]: *** [include/mysqld_error.h] Error 2
make[2]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make[1]: *** [extra/CMakeFiles/GenError.dir/all] Error 2
make[1]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make: *** [all] Error 2
有個comp_err無法執行,先找出它在哪
$ find ./ -name "comp_err" -print
./extra/comp_err
看一下屬性
$ file ./extra/comp_err
./extra/comp_err: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.14, not stripped
嗯,看來需要先在host side compile mysql.
3.Compile mysql-5.5.8 for host
$ cmake -DMYSQL_DATADIR=/var/lib/mysql/data -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DEXTRA_CHARSETS=all -DMYSQL_UNIX_ADDR=/tmp/mysqld.sock -DMYSQL_TCP_PORT=3306 -DENABLED_LOCAL_INFILE=1 -DWITH_PARTITION_STORAGE_ENGINE=1 -DWITH_INNOBASE_STORAGE_ENGINE=1 -DMYSQL_USER=mysql -DWITH_EMBEDDED_SERVER=1 -DSTACK_DIRECTION=1
$ make VERBOSE=1
4.Continue cross compile mysql-5.5.8
以host版本comp_err覆蓋
$ cp ../../mysql-5.5.8/extra/comp_err extra/
$ make VERBOSE=1
出現錯誤
[ 75%] Building CXX object client/CMakeFiles/mysql.dir/sql_string.cc.o
cd /home/gigijoe/BeagleBoard/mysql-5.5.8/client && /opt/arm-2008q1/bin/arm-none-linux-gnueabi-g++ -DHAVE_CONFIG_H -DHAVE_DLOPEN -Wall -Wno-unused-parameter -fno-implicit-templates -fno-exceptions -fno-rtti -O2 -g -DDBUG_OFF -I/home/gigijoe/BeagleBoard/mysql-5.5.8/include -I/home/gigijoe/BeagleBoard/mysql-5.5.8/libmysql -I/home/gigijoe/BeagleBoard/mysql-5.5.8/regex -I/home/gigijoe/BeagleBoard/mysql-5.5.8/sql -I/home/gigijoe/BeagleBoard/mysql-5.5.8/strings -I/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit -I/home/gigijoe/BeagleBoard/mysql-5.5.8/client -o CMakeFiles/mysql.dir/sql_string.cc.o -c /home/gigijoe/BeagleBoard/mysql-5.5.8/client/sql_string.cc
Linking CXX executable mysql
cd /home/gigijoe/BeagleBoard/mysql-5.5.8/client && /usr/bin/cmake -E cmake_link_script CMakeFiles/mysql.dir/link.txt --verbose=1
/opt/arm-2008q1/bin/arm-none-linux-gnueabi-g++ -Wall -Wno-unused-parameter -fno-implicit-templates -fno-exceptions -fno-rtti -O2 -g -DDBUG_OFF CMakeFiles/mysql.dir/completion_hash.cc.o CMakeFiles/mysql.dir/mysql.cc.o CMakeFiles/mysql.dir/readline.cc.o CMakeFiles/mysql.dir/sql_string.cc.o -o mysql -lpthread ../libmysql/libmysqlclient.a ../cmd-line-utils/libedit/libedit.a -lz -lm -lrt -ldl -lpthread -lcurses
/opt/arm-2008q1/bin/../lib/gcc/arm-none-linux-gnueabi/4.2.3/../../../../arm-none-linux-gnueabi/bin/ld: cannot find -lcurses
collect2: ld returned 1 exit status
make[2]: *** [client/mysql] Error 1
make[2]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make[1]: *** [client/CMakeFiles/mysql.dir/all] Error 2
make[1]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make: *** [all] Error 2
用以下方式修正
編輯
/home/gigijoe/BeagleBoard/mysql-5.5.8/client/CMakeFiles/mysql.dir/link.txt
/home/gigijoe/BeagleBoard/mysql-5.5.8/libmysqld/examples/CMakeFiles/mysql_embedded.dir/link.txt
將 -lcurses 成 -lncurses
$ make VERBOSE=1
出現錯誤
[ 76%] Generating mysql_fix_privilege_tables_sql.c
cd /home/gigijoe/BeagleBoard/mysql-5.5.8/scripts && /usr/bin/cmake -E chdir /home/gigijoe/BeagleBoard/mysql-5.5.8/scripts /bin/cat mysql_system_tables.sql mysql_system_tables_fix.sql > /home/gigijoe/BeagleBoard/mysql-5.5.8/scripts/mysql_fix_privilege_tables.sql
cd /home/gigijoe/BeagleBoard/mysql-5.5.8/scripts && /home/gigijoe/BeagleBoard/mysql-5.5.8/scripts/comp_sql mysql_fix_privilege_tables mysql_fix_privilege_tables.sql mysql_fix_privilege_tables_sql.c
/home/gigijoe/BeagleBoard/mysql-5.5.8/scripts/comp_sql: 1: Syntax error: word unexpected (expecting ")")
make[2]: *** [scripts/mysql_fix_privilege_tables_sql.c] Error 2
make[2]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make[1]: *** [scripts/CMakeFiles/GenFixPrivs.dir/all] Error 2
make[1]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make: *** [all] Error 2
以host版本comp_sql覆蓋
$ cp ../../mysql-5.5.8/scripts/comp_sql scripts/
$ make VERBOSE=1
出現錯誤
[ 78%] Generating lex_hash.h
cd /home/gigijoe/BeagleBoard/mysql-5.5.8/sql && ./gen_lex_hash > lex_hash.h
./gen_lex_hash: 1: Syntax error: word unexpected (expecting ")")
make[2]: *** [sql/lex_hash.h] Error 2
make[2]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make[1]: *** [sql/CMakeFiles/GenServerSource.dir/all] Error 2
make[1]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make: *** [all] Error 2
以host版本gen_lex_hash覆蓋
cp ../../mysql-5.5.8/sql/gen_lex_hash sql/
$ make VERBOSE=1
$ make install
HTTP server選擇lighttpd.整個cross comiple流程大致是先build MySQL,
因為PHP需要連結MySQL,再來是bulid PHP 最後才是lighttpd.
ARM cross compile 是 CodeSourcery 2008q1版本.
首先了解一下cross compile搜尋路徑
$ arm-none-linux-gnueabi-gcc -print-search-dirs
install: /opt/arm-2008q1/bin/../lib/gcc/arm-none-linux-gnueabi/4.2.3/
programs: =/opt/arm-2008q1/bin/../libexec/gcc/arm-none-linux-gnueabi/4.2.3/:/opt/arm-2008q1/bin/../libexec/gcc/:/opt/arm-2008q1/bin/../lib/gcc/arm-none-linux-gnueabi/4.2.3/../../../../arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi/4.2.3/:/opt/arm-2008q1/bin/../lib/gcc/arm-none-linux-gnueabi/4.2.3/../../../../arm-none-linux-gnueabi/bin/
libraries: =/opt/arm-2008q1/bin/../lib/gcc/arm-none-linux-gnueabi/4.2.3/:/opt/arm-2008q1/bin/../lib/gcc/:/opt/arm-2008q1/bin/../lib/gcc/arm-none-linux-gnueabi/4.2.3/../../../../arm-none-linux-gnueabi/lib/arm-none-linux-gnueabi/4.2.3/:/opt/arm-2008q1/bin/../lib/gcc/arm-none-linux-gnueabi/4.2.3/../../../../arm-none-linux-gnueabi/lib/:/opt/arm-2008q1/bin/../arm-none-linux-gnueabi/libc/lib/arm-none-linux-gnueabi/4.2.3/:/opt/arm-2008q1/bin/../arm-none-linux-gnueabi/libc/lib/:/opt/arm-2008q1/bin/../arm-none-linux-gnueabi/libc/usr/lib/arm-none-linux-gnueabi/4.2.3/:/opt/arm-2008q1/bin/../arm-none-linux-gnueabi/libc/usr/lib/
由以上libraries搜尋路徑偶選擇 /opt/arm-2008q1/arm-none-linux-gnueabi/libc/usr 作為相關所需libraries的安裝位置
1.Download & cross compile pcre-8.12 & ncurses-5.7
$ cd pcre-8.12/
$ CC=arm-none-linux-gnueabi-gcc AR=arm-none-linux-gnueabi-ar CXX=arm-none-linux-gnueabi-g++ ./configure --host=arm-linux --target=arm-linux --prefix=/opt/arm-2008q1/arm-none-linux-gnueabi/libc/usr --cache-file=/dev/null
$ make
$ sudo PATH=$PATH:/opt/arm-2008q1/bin make install
$ cd ../ncurses-5.7
$ CC=arm-none-linux-gnueabi-gcc AR=arm-none-linux-gnueabi-ar CXX=arm-none-linux-gnueabi-g++ ./configure --host=arm-linux --target=arm-linux --prefix=/opt/arm-2008q1/arm-none-linux-gnueabi/libc/usr --cache-file=/dev/null
$ make
$ sudo PATH=$PATH:/opt/arm-2008q1/bin make install
在make install 時加上PATH=$PATH:/opt/arm-2008q1/bin是為了在root權限下也能執行cross compiler.
2.Cross compile mysql-5.5.8
MySQL在5.5之後不在使用autoconf系統而採cmake.
建立 toolchain.cmake 內容如下
# this one is important
SET(CMAKE_SYSTEM_NAME Linux)
#this one not so much
SET(CMAKE_SYSTEM_VERSION 1)
# specify the cross compiler
SET(CMAKE_C_COMPILER /opt/arm-2008q1/bin/arm-none-linux-gnueabi-gcc)
SET(CMAKE_CXX_COMPILER /opt/arm-2008q1/bin/arm-none-linux-gnueabi-g++)
SET(CMAKE_STRIP /opt/arm-2008q1/bin/arm-none-linux-gnueabi-strip)
# where is the target environment
SET(CMAKE_FIND_ROOT_PATH /opt/arm-2008q1/arm-none-linux-gnueabi/libc)
# search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
接著執行cmake
$ cmake -DCMAKE_TOOLCHAIN_FILE=./toolchain.cmake -DMYSQL_DATADIR=/var/lib/mysql/data -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DEXTRA_CHARSETS=all -DMYSQL_UNIX_ADDR=/tmp/mysqld.sock -DMYSQL_TCP_PORT=3306 -DENABLED_LOCAL_INFILE=1 -DWITH_PARTITION_STORAGE_ENGINE=1 -DWITH_INNOBASE_STORAGE_ENGINE=1 -DMYSQL_USER=mysql -DCMAKE_INSTALL_PREFIX=/home/gigijoe/BeagleBoard/rootfs/usr/local/mysql -DWITH_EMBEDDED_SERVER=1 -DCMAKE_C_COMPILER=arm-none-linux-gnueabi-gcc -DCMAKE_CXX_COMPILER=arm-none-linux-gnueabi-g++ -DSTACK_DIRECTION=1
$ make VERBOSE=1
出現錯誤
[ 2%] Building C object cmd-line-utils/libedit/CMakeFiles/edit.dir/term.c.o
cd /home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit && /opt/arm-2008q1/bin/arm-none-linux-gnueabi-gcc -DHAVE_CONFIG_H -Wall -O2 -g -DDBUG_OFF -I/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit -I/home/gigijoe/BeagleBoard/mysql-5.5.8/include -o CMakeFiles/edit.dir/term.c.o -c /home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c:59:20: error: curses.h: No such file or directory
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c: In function 'term_set':
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c:928: warning: implicit declaration of function 'tgetent'
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c:946: warning: implicit declaration of function 'tgetflag'
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c:955: warning: implicit declaration of function 'tgetnum'
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c:959: warning: implicit declaration of function 'tgetstr'
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c:960: warning: passing argument 3 of 'term_alloc' makes pointer from integer without a cast
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c: In function 'term_tputs':
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c:1261: warning: implicit declaration of function 'tputs'
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c: In function 'term_echotc':
/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c:1560: warning: assignment makes pointer from integer without a cast
make[2]: *** [cmd-line-utils/libedit/CMakeFiles/edit.dir/term.c.o] Error 1
make[2]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make[1]: *** [cmd-line-utils/libedit/CMakeFiles/edit.dir/all] Error 2
make[1]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make: *** [all] Error 2
修改 /home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit/term.c
#ifdef HAVE_CURSES_H
-#include
+#include
#endif
#ifdef HAVE_NCURSES_H
-#include
+#include
#endif
/* Don't use Solaris's term.h. */
#if (defined(HAVE_TERM_H) && !defined(__SunOS))
-#include
+#include
#endif
再次嘗試
$ make VERBOSE=1
出現錯誤
[ 28%] Generating ../include/mysqld_error.h, ../sql/share/english/errmsg.sys
cd /home/gigijoe/BeagleBoard/mysql-5.5.8/extra && ./comp_err --charset=/home/gigijoe/BeagleBoard/mysql-5.5.8/sql/share/charsets --out-dir=/home/gigijoe/BeagleBoard/mysql-5.5.8/sql/share/ --header_file=/home/gigijoe/BeagleBoard/mysql-5.5.8/include/mysqld_error.h --name_file=/home/gigijoe/BeagleBoard/mysql-5.5.8/include/mysqld_ername.h --state_file=/home/gigijoe/BeagleBoard/mysql-5.5.8/include/sql_state.h --in_file=/home/gigijoe/BeagleBoard/mysql-5.5.8/sql/share/errmsg-utf8.txt
./comp_err: 1: Syntax error: word unexpected (expecting ")")
make[2]: *** [include/mysqld_error.h] Error 2
make[2]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make[1]: *** [extra/CMakeFiles/GenError.dir/all] Error 2
make[1]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make: *** [all] Error 2
有個comp_err無法執行,先找出它在哪
$ find ./ -name "comp_err" -print
./extra/comp_err
看一下屬性
$ file ./extra/comp_err
./extra/comp_err: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.14, not stripped
嗯,看來需要先在host side compile mysql.
3.Compile mysql-5.5.8 for host
$ cmake -DMYSQL_DATADIR=/var/lib/mysql/data -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DEXTRA_CHARSETS=all -DMYSQL_UNIX_ADDR=/tmp/mysqld.sock -DMYSQL_TCP_PORT=3306 -DENABLED_LOCAL_INFILE=1 -DWITH_PARTITION_STORAGE_ENGINE=1 -DWITH_INNOBASE_STORAGE_ENGINE=1 -DMYSQL_USER=mysql -DWITH_EMBEDDED_SERVER=1 -DSTACK_DIRECTION=1
$ make VERBOSE=1
4.Continue cross compile mysql-5.5.8
以host版本comp_err覆蓋
$ cp ../../mysql-5.5.8/extra/comp_err extra/
$ make VERBOSE=1
出現錯誤
[ 75%] Building CXX object client/CMakeFiles/mysql.dir/sql_string.cc.o
cd /home/gigijoe/BeagleBoard/mysql-5.5.8/client && /opt/arm-2008q1/bin/arm-none-linux-gnueabi-g++ -DHAVE_CONFIG_H -DHAVE_DLOPEN -Wall -Wno-unused-parameter -fno-implicit-templates -fno-exceptions -fno-rtti -O2 -g -DDBUG_OFF -I/home/gigijoe/BeagleBoard/mysql-5.5.8/include -I/home/gigijoe/BeagleBoard/mysql-5.5.8/libmysql -I/home/gigijoe/BeagleBoard/mysql-5.5.8/regex -I/home/gigijoe/BeagleBoard/mysql-5.5.8/sql -I/home/gigijoe/BeagleBoard/mysql-5.5.8/strings -I/home/gigijoe/BeagleBoard/mysql-5.5.8/cmd-line-utils/libedit -I/home/gigijoe/BeagleBoard/mysql-5.5.8/client -o CMakeFiles/mysql.dir/sql_string.cc.o -c /home/gigijoe/BeagleBoard/mysql-5.5.8/client/sql_string.cc
Linking CXX executable mysql
cd /home/gigijoe/BeagleBoard/mysql-5.5.8/client && /usr/bin/cmake -E cmake_link_script CMakeFiles/mysql.dir/link.txt --verbose=1
/opt/arm-2008q1/bin/arm-none-linux-gnueabi-g++ -Wall -Wno-unused-parameter -fno-implicit-templates -fno-exceptions -fno-rtti -O2 -g -DDBUG_OFF CMakeFiles/mysql.dir/completion_hash.cc.o CMakeFiles/mysql.dir/mysql.cc.o CMakeFiles/mysql.dir/readline.cc.o CMakeFiles/mysql.dir/sql_string.cc.o -o mysql -lpthread ../libmysql/libmysqlclient.a ../cmd-line-utils/libedit/libedit.a -lz -lm -lrt -ldl -lpthread -lcurses
/opt/arm-2008q1/bin/../lib/gcc/arm-none-linux-gnueabi/4.2.3/../../../../arm-none-linux-gnueabi/bin/ld: cannot find -lcurses
collect2: ld returned 1 exit status
make[2]: *** [client/mysql] Error 1
make[2]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make[1]: *** [client/CMakeFiles/mysql.dir/all] Error 2
make[1]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make: *** [all] Error 2
用以下方式修正
編輯
/home/gigijoe/BeagleBoard/mysql-5.5.8/client/CMakeFiles/mysql.dir/link.txt
/home/gigijoe/BeagleBoard/mysql-5.5.8/libmysqld/examples/CMakeFiles/mysql_embedded.dir/link.txt
將 -lcurses 成 -lncurses
$ make VERBOSE=1
出現錯誤
[ 76%] Generating mysql_fix_privilege_tables_sql.c
cd /home/gigijoe/BeagleBoard/mysql-5.5.8/scripts && /usr/bin/cmake -E chdir /home/gigijoe/BeagleBoard/mysql-5.5.8/scripts /bin/cat mysql_system_tables.sql mysql_system_tables_fix.sql > /home/gigijoe/BeagleBoard/mysql-5.5.8/scripts/mysql_fix_privilege_tables.sql
cd /home/gigijoe/BeagleBoard/mysql-5.5.8/scripts && /home/gigijoe/BeagleBoard/mysql-5.5.8/scripts/comp_sql mysql_fix_privilege_tables mysql_fix_privilege_tables.sql mysql_fix_privilege_tables_sql.c
/home/gigijoe/BeagleBoard/mysql-5.5.8/scripts/comp_sql: 1: Syntax error: word unexpected (expecting ")")
make[2]: *** [scripts/mysql_fix_privilege_tables_sql.c] Error 2
make[2]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make[1]: *** [scripts/CMakeFiles/GenFixPrivs.dir/all] Error 2
make[1]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make: *** [all] Error 2
以host版本comp_sql覆蓋
$ cp ../../mysql-5.5.8/scripts/comp_sql scripts/
$ make VERBOSE=1
出現錯誤
[ 78%] Generating lex_hash.h
cd /home/gigijoe/BeagleBoard/mysql-5.5.8/sql && ./gen_lex_hash > lex_hash.h
./gen_lex_hash: 1: Syntax error: word unexpected (expecting ")")
make[2]: *** [sql/lex_hash.h] Error 2
make[2]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make[1]: *** [sql/CMakeFiles/GenServerSource.dir/all] Error 2
make[1]: Leaving directory `/home/gigijoe/BeagleBoard/mysql-5.5.8'
make: *** [all] Error 2
以host版本gen_lex_hash覆蓋
cp ../../mysql-5.5.8/sql/gen_lex_hash sql/
$ make VERBOSE=1
$ make install
2011年1月24日 星期一
Rowboat Android u-boot env
Texas Instruments X-Loader 1.4.2 (Feb 19 2009 - 12:01:24)
Loading u-boot.bin from nand
U-Boot 2009.11 (Feb 23 2010 - 15:33:48)
OMAP3530-GP ES3.1, CPU-OPP2 L3-165MHz
OMAP3 Beagle board + LPDDR/NAND
I2C: ready
DRAM: 256 MB
NAND: 256 MiB
In: serial
Out: serial
Err: serial
Board revision C4
Die ID #799e000400000000040373051500e007
Hit any key to stop autoboot: 0
OMAP3 beagleboard.org # printenv
bootcmd=if mmcinit; then if run loadbootscript; then run bootscript; else if run loaduimage; then if run loadramdisk; then run ramboot; else run mmcboot; fii
bootdelay=10
baudrate=115200
loadaddr=0x80200000
rdaddr=0x81600000
console=ttyS2,115200n8
mmcargs=setenv bootargs console=${console} ${optargs} root=/dev/mmcblk0p2 rw rootfstype=ext3 rootwait
ramargs=setenv bootargs console=${console} ${optargs} root=/dev/ram0 rw ramdisk_size=32768 initrd=${rdaddr},32M
jffs2args=setenv bootargs console=${console} ${optargs} root=/dev/mtdblock4 rw rootfstype=jffs2
loadbootscript=fatload mmc 0 ${loadaddr} boot.scr
bootscript=echo Running bootscript from mmc ...; autoscr ${loadaddr}
loaduimage=fatload mmc 0 ${loadaddr} uImage.bin
loadramdisk=fatload mmc 0 ${rdaddr} ramdisk.gz
ramboot=echo Booting from ramdisk.gz ...; run ramargs; bootm ${loadaddr}
mmcboot=echo Booting from mmc ...; run mmcargs; bootm ${loadaddr}
usbtty=cdc_acm
stdout=serial,usbtty
stdin=serial,usbtty
stderr=serial,usbtty
serial=799e000400000000040373051500e007
dieid#=799e000400000000040373051500e007
ubifsargs=setenv bootargs console=${console} ${optargs} mem=88M@0x80000000 mem=128M@0x88000000 root=ubi0:rootfs ubi.mtd=4 rw rootfstype=ubifs
nandboot=echo Booting from nand ...; run ubifsargs; nand read ${loadaddr} 280000 400000; bootm ${loadaddr}
optargs=init=/init omapdss.def_disp=dvi omapfb.mode=dvi:720x480MR-16
Environment size: 1561/131068 bytes
OMAP3 beagleboard.org #
NAND read: device 0 offset 0x280000, size 0x400000
4194304 bytes read: OK
## Booting kernel from Legacy Image at 80200000 ...
Image Name: Linux-2.6.32
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2529392 Bytes = 2.4 MB
Load Address: 80008000
Entry Point: 80008000
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux..........................................................................................................................................
Linux version 2.6.32 (gigijoe@gigijoe-laptop) (gcc version 4.4.0 (GCC) ) #4 Wed Jan 5 02:16:23 CST 2011
CPU: ARMv7 Processor [411fc083] revision 3 (ARMv7), cr=10c53c7f
CPU: VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
Machine: OMAP3 Beagle Board
Memory policy: ECC disabled, Data cache writeback
OMAP3430/3530 ES3.1 (l2cache iva sgx neon isp 720m )
SRAM: Mapped pa 0x40200000 to va 0xfe400000 size: 0x100000
Reserving 4194304 bytes SDRAM for VRAM
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 54784
Kernel command line: console=ttyS2,115200n8 init=/init omapdss.def_disp=dvi omapfb.mode=dvi:720x480MR-16 mem=88M@0x80000000 mem=128M@0x88000000 root=ubi0:ros
PID hash table entries: 1024 (order: 0, 4096 bytes)
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 88MB 128MB = 216MB total
Memory: 209408KB available (4368K code, 822K data, 172K init, 0K highmem)
Loading u-boot.bin from nand
U-Boot 2009.11 (Feb 23 2010 - 15:33:48)
OMAP3530-GP ES3.1, CPU-OPP2 L3-165MHz
OMAP3 Beagle board + LPDDR/NAND
I2C: ready
DRAM: 256 MB
NAND: 256 MiB
In: serial
Out: serial
Err: serial
Board revision C4
Die ID #799e000400000000040373051500e007
Hit any key to stop autoboot: 0
OMAP3 beagleboard.org # printenv
bootcmd=if mmcinit; then if run loadbootscript; then run bootscript; else if run loaduimage; then if run loadramdisk; then run ramboot; else run mmcboot; fii
bootdelay=10
baudrate=115200
loadaddr=0x80200000
rdaddr=0x81600000
console=ttyS2,115200n8
mmcargs=setenv bootargs console=${console} ${optargs} root=/dev/mmcblk0p2 rw rootfstype=ext3 rootwait
ramargs=setenv bootargs console=${console} ${optargs} root=/dev/ram0 rw ramdisk_size=32768 initrd=${rdaddr},32M
jffs2args=setenv bootargs console=${console} ${optargs} root=/dev/mtdblock4 rw rootfstype=jffs2
loadbootscript=fatload mmc 0 ${loadaddr} boot.scr
bootscript=echo Running bootscript from mmc ...; autoscr ${loadaddr}
loaduimage=fatload mmc 0 ${loadaddr} uImage.bin
loadramdisk=fatload mmc 0 ${rdaddr} ramdisk.gz
ramboot=echo Booting from ramdisk.gz ...; run ramargs; bootm ${loadaddr}
mmcboot=echo Booting from mmc ...; run mmcargs; bootm ${loadaddr}
usbtty=cdc_acm
stdout=serial,usbtty
stdin=serial,usbtty
stderr=serial,usbtty
serial=799e000400000000040373051500e007
dieid#=799e000400000000040373051500e007
ubifsargs=setenv bootargs console=${console} ${optargs} mem=88M@0x80000000 mem=128M@0x88000000 root=ubi0:rootfs ubi.mtd=4 rw rootfstype=ubifs
nandboot=echo Booting from nand ...; run ubifsargs; nand read ${loadaddr} 280000 400000; bootm ${loadaddr}
optargs=init=/init omapdss.def_disp=dvi omapfb.mode=dvi:720x480MR-16
Environment size: 1561/131068 bytes
OMAP3 beagleboard.org #
NAND read: device 0 offset 0x280000, size 0x400000
4194304 bytes read: OK
## Booting kernel from Legacy Image at 80200000 ...
Image Name: Linux-2.6.32
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2529392 Bytes = 2.4 MB
Load Address: 80008000
Entry Point: 80008000
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux..........................................................................................................................................
Linux version 2.6.32 (gigijoe@gigijoe-laptop) (gcc version 4.4.0 (GCC) ) #4 Wed Jan 5 02:16:23 CST 2011
CPU: ARMv7 Processor [411fc083] revision 3 (ARMv7), cr=10c53c7f
CPU: VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
Machine: OMAP3 Beagle Board
Memory policy: ECC disabled, Data cache writeback
OMAP3430/3530 ES3.1 (l2cache iva sgx neon isp 720m )
SRAM: Mapped pa 0x40200000 to va 0xfe400000 size: 0x100000
Reserving 4194304 bytes SDRAM for VRAM
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 54784
Kernel command line: console=ttyS2,115200n8 init=/init omapdss.def_disp=dvi omapfb.mode=dvi:720x480MR-16 mem=88M@0x80000000 mem=128M@0x88000000 root=ubi0:ros
PID hash table entries: 1024 (order: 0, 4096 bytes)
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 88MB 128MB = 216MB total
Memory: 209408KB available (4368K code, 822K data, 172K init, 0K highmem)
2011年1月20日 星期四
BeagleBoard PWM with RC Servo
OMAP3 PWM resource
http://elinux.org/BeagleBoardPWM
http://www.jumpnowtek.com/index.php?option=com_content&view=article&id=56&Itemid=63
RC Servo resource
http://robot.avayanex.com/?tag=rc-servo
http://robot.pixnet.net/blog/post/26779024
RC Servo duty cycle 最短要 20.83 ms, 也就是48Hz 以下.
Pulse width範圍在 1~2.5 ms左右,各廠牌型號Servo略有不同
2.OMAP3 PWM
OMAP3 總共支援 4 個PWM channel, 在BeagleBoard線路有拉出來的有3組,分別是PWM 9, 10, 11
位於Expansion Connector Pin 4, 8, 10. (參考BBSRM Table 20)
3.kernel 需要稍作修改(2.6.29)
將mux設為PWM pin(參考 OMAP35x Technical Reference Manual (Rev.M) 7.4.4.3 p.772)
arch/arm/mach-omap2/mux.c
...
#if 0
/* UART2 */
MUX_CFG_34XX("AA25_34XX_UART2_TX", 0x178,
OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
MUX_CFG_34XX("AD25_34XX_UART2_RX", 0x17A,
OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP)
MUX_CFG_34XX("AB25_34XX_UART2_RTS", 0x176,
OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
MUX_CFG_34XX("AB26_34XX_UART2_CTS", 0x174,
OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP)
#endif
/* PWM */
/* OMAP35x Technical Reference Manual (Rev.M) 7.4.4.3 p.772*/
MUX_CFG_34XX("AA25_34XX_UART2_TX", 0x178,
OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_OUTPUT)
MUX_CFG_34XX("AD25_34XX_UART2_RX", 0x17A,
OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_OUTPUT)
MUX_CFG_34XX("AB25_34XX_UART2_RTS", 0x176,
OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_OUTPUT)
MUX_CFG_34XX("AB26_34XX_UART2_CTS", 0x174,
OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_OUTPUT)
再來要disable CONFIG_OMAP_RESET_CLOCKS這樣PWM才能正常工作.
3.OMAP3 PWM driver
https://github.com/scottellis/omap3-pwm
https://github.com/neo01124/omap3-pwm
以上面兩個PWM driver為基礎作修改可分別控制3組PWM.
Device node
/dev/pwm/9
/dev/pwm/10
/dev/pwm/11
Clock source從文件及source code所了解的應該是可以更改.
我實際測試的結果是
PWM9 13MHz
PWM10 32KHz
PWM11 32KHz
不只是更改GPTi input frequency 這麼單純,必須實際修改omap34xx clock source.
搞了半天還是不能把32KHz 換成 13MHz
Frequency預設是48Hz
13MHz clock source 精確度很好.
32KHz clock source 的 duty cycle 範圍約在 4 ~ 13%, 約只有50個刻度.因此精確度並不高.
4.PWM Driver source
From github : git@github.com:gigijoe/omap3-pwm.git
omap_pwm.h
/*
Copyright (c) 2010, Scott Ellis
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY Scott Ellis ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL Scott Ellis BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Register definitions used by the pwm driver.
Some for the PADCONF pin muxing, the rest for the PWM timer control.
*/
#ifndef PWM_H
#define PWM_H
#define OMAP34XX_PADCONF_START 0x48002030
#define OMAP34XX_PADCONF_SIZE 0x05cc
#define GPT8_MUX_OFFSET (0x4800217A - OMAP34XX_PADCONF_START)
#define GPT9_MUX_OFFSET (0x48002174 - OMAP34XX_PADCONF_START)
#define GPT10_MUX_OFFSET (0x48002176 - OMAP34XX_PADCONF_START)
#define GPT11_MUX_OFFSET (0x48002178 - OMAP34XX_PADCONF_START)
#define PWM_ENABLE_MUX 0x0002 /* IDIS | PTD | DIS | M2 */
#define CLK_32K_FREQ 32768
#define CLK_13K_FREQ 13312
#define CLK_SYS_FREQ 13000000
#define GPTIMER8 0x4903E000
#define GPTIMER9 0x49040000
#define GPTIMER10 0x48086000
#define GPTIMER11 0x48088000
#define GPT_REGS_PAGE_SIZE 4096
#define PWM8_CTL_BASE GPTIMER8
#define PWM9_CTL_BASE GPTIMER9
#define PWM10_CTL_BASE GPTIMER10
#define PWM11_CTL_BASE GPTIMER11
/* GPT register offsets */
#define GPT_TIOCP_CFG 0x010
#define GPT_TISTAT 0x014
#define GPT_TISR 0x018
#define GPT_TIER 0x01C
#define GPT_TWER 0x020
#define GPT_TCLR 0x024
#define GPT_TCRR 0x028
#define GPT_TLDR 0x02C
#define GPT_TTGR 0x030
#define GPT_TWPS 0x034
#define GPT_TMAR 0x038
#define GPT_TCAR1 0x03C
#define GPT_TSICR 0x040
#define GPT_TCAR2 0x044
#define GPT_TPIR 0x048
#define GPT_TNIR 0x04C
#define GPT_TCVR 0x050
#define GPT_TOCR 0x054
#define GPT_TOWR 0x058
/* TCLR bits for PWM */
#define GPT_TCLR_ST (1 << 0) /* stop/start */
#define GPT_TCLR_AR (1 << 1) /* one shot/auto-reload */
#define GPT_TCLR_PTV_MASK (7 << 2) /* prescaler value 2^(PTV + 1) */
#define GPT_TCLR_PRE (1 << 5) /* disable/enable prescaler */
#define GPT_TCLR_CE (1 << 6) /* disable/enable compare */
#define GPT_TCLR_SCPWM (1 << 7) /* PWM value when off */
#define GPT_TCLR_TCM_MASK (3 << 8) /* transition capture mode */
#define GPT_TCLR_TRG_MASK (3 << 10) /* trigger output mode */
#define GPT_TCLR_TRG_OVFL (1 << 10) /* trigger on overflow */
#define GPT_TCLR_TRG_OVFL_MATCH (2 << 10) /* trigger on overflow and match */
#define GPT_TCLR_PT (1 << 12) /* pulse/toggle modulation */
#define GPT_TCLR_CAPT_MODE (1 << 13) /* capture mode config */
#define GPT_TCLR_GPO_CFG (1 << 14) /* pwm or capture mode */
/* Ioctl definitions */
#define PWM_IOC_MAGIC 0x00
#define PWM_SET_DUTYCYCLE _IOW(PWM_IOC_MAGIC , 1, int)
#define PWM_GET_DUTYCYCLE _IOW(PWM_IOC_MAGIC , 2, int)
#define PWM_SET_FREQUENCY _IOW(PWM_IOC_MAGIC , 3, int)
#define PWM_GET_FREQUENCY _IOW(PWM_IOC_MAGIC , 4, int)
#define PWM_ON _IO(PWM_IOC_MAGIC , 5)
#define PWM_OFF _IO(PWM_IOC_MAGIC , 6)
#define PWM_SET_POLARITY _IOW(PWM_IOC_MAGIC , 7, int)
#define PWM_SET_CLK _IOW(PWM_IOC_MAGIC , 8, int)
#define PWM_SET_PRE _IOW(PWM_IOC_MAGIC , 9, int)
#define PWM_PLUS_DUTYCYCLE _IOW(PWM_IOC_MAGIC , 10, int)
#define PWM_MINUS_DUTYCYCLE _IOW(PWM_IOC_MAGIC , 11, int)
#define PWM_IOC_MAXNR 11
#endif /* ifndef PWM_H */
omap_pwm.c
/*
Copyright (c) 2010, Scott Ellis
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY Scott Ellis ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL Scott Ellis BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "omap_pwm.h"
/* default frequency of 1 kHz */
//#define DEFAULT_TLDR 0xFFFFFFE0
/* default frequency of 48 Hz */
//#define DEFAULT_TLDR 0xFFFFFD55
/* default 50% duty cycle */
/* TMAR = (0xFFFFFFFF - ((0xFFFFFFFF - (DEFAULT_TLDR + 1)) / 2)) */
//#define DEFAULT_TMAR 0xFFFFFFEF
//#define DEFAULT_TMAR 0xFFFFFEAB
/* default TCLR is off state */
#define DEFAULT_TCLR (GPT_TCLR_PT | GPT_TCLR_TRG_OVFL_MATCH | GPT_TCLR_CE | GPT_TCLR_AR)
//#define DEFAULT_PWM_FREQUENCY 1024
#define DEFAULT_PWM_FREQUENCY 48
static int defaultFrequency = DEFAULT_PWM_FREQUENCY;
module_param(defaultFrequency, int, S_IRUGO);
MODULE_PARM_DESC(defaultFrequency, "The PWM frequency, power of two, max of 16384");
#define USER_BUFF_SIZE 128
struct gpt {
u32 timer_num;
u32 mux_offset;
u32 gpt_base;
u32 input_freq;
u32 old_mux;
u32 tldr;
u32 tmar;
u32 tclr;
u32 num_freqs;
};
struct pwm_dev {
int frequency;
struct semaphore sem;
struct gpt gpt;
char *user_buff;
};
static dev_t devt;
static struct cdev cdev;
static struct pwm_dev pwm9_dev;
static struct pwm_dev pwm10_dev;
static struct pwm_dev pwm11_dev;
static int init_mux(struct pwm_dev *pwm_dev)
{
void __iomem *base;
base = ioremap(OMAP34XX_PADCONF_START, OMAP34XX_PADCONF_SIZE);
if (!base) {
printk(KERN_ALERT "init_mux(): ioremap() failed\n");
return -1;
}
pwm_dev->gpt.old_mux = ioread16(base + pwm_dev->gpt.mux_offset);
iowrite16(PWM_ENABLE_MUX, base + pwm_dev->gpt.mux_offset);
iounmap(base);
return 0;
}
static int restore_mux(struct pwm_dev *pwm_dev)
{
void __iomem *base;
if (pwm_dev->gpt.old_mux) {
base = ioremap(OMAP34XX_PADCONF_START, OMAP34XX_PADCONF_SIZE);
if (!base) {
printk(KERN_ALERT "restore_mux(): ioremap() failed\n");
return -1;
}
iowrite16(pwm_dev->gpt.old_mux, base + pwm_dev->gpt.mux_offset);
iounmap(base);
}
return 0;
}
static int set_pwm_frequency(struct pwm_dev *pwm_dev, int frequency)
{
void __iomem *base;
base = ioremap(pwm_dev->gpt.gpt_base, GPT_REGS_PAGE_SIZE);
if (!base) {
printk(KERN_ALERT "set_pwm_frequency(): ioremap failed\n");
return -1;
}
if (frequency < 0) {
frequency = DEFAULT_PWM_FREQUENCY;
} else {
/* only powers of two, for simplicity */
//frequency &= ~0x01;
if (frequency > (pwm_dev->gpt.input_freq / 2))
frequency = pwm_dev->gpt.input_freq / 2;
else if (frequency == 0)
frequency = DEFAULT_PWM_FREQUENCY;
}
pwm_dev->frequency = frequency;
/* PWM_FREQ = 32768 / ((0xFFFF FFFF - TLDR) + 1) */
pwm_dev->gpt.tldr = 0xFFFFFFFF - ((pwm_dev->gpt.input_freq / pwm_dev->frequency) - 1);
/* just for convenience */
pwm_dev->gpt.num_freqs = 0xFFFFFFFE - pwm_dev->gpt.tldr;
iowrite32(pwm_dev->gpt.tldr, base + GPT_TLDR);
/* initialize TCRR to TLDR, have to start somewhere */
iowrite32(pwm_dev->gpt.tldr, base + GPT_TCRR);
iounmap(base);
return 0;
}
static int pwm_off(struct pwm_dev *pwm_dev)
{
void __iomem *base;
base = ioremap(pwm_dev->gpt.gpt_base, GPT_REGS_PAGE_SIZE);
if (!base) {
printk(KERN_ALERT "pwm_off(): ioremap failed\n");
return -1;
}
pwm_dev->gpt.tclr &= ~GPT_TCLR_ST;
iowrite32(pwm_dev->gpt.tclr, base + GPT_TCLR);
iounmap(base);
return 0;
}
static int pwm_on(struct pwm_dev *pwm_dev)
{
void __iomem *base;
base = ioremap(pwm_dev->gpt.gpt_base, GPT_REGS_PAGE_SIZE);
if (!base) {
printk(KERN_ALERT "pwm_on(): ioremap failed\n");
return -1;
}
/* set the duty cycle */
iowrite32(pwm_dev->gpt.tmar, base + GPT_TMAR);
/* now turn it on */
pwm_dev->gpt.tclr = ioread32(base + GPT_TCLR);
pwm_dev->gpt.tclr |= GPT_TCLR_ST;
iowrite32(pwm_dev->gpt.tclr, base + GPT_TCLR);
iounmap(base);
return 0;
}
static int scpwm(struct pwm_dev *pwm_dev, int sc)
{
void __iomem *base;
base = ioremap(pwm_dev->gpt.gpt_base, GPT_REGS_PAGE_SIZE);
if (!base) {
printk(KERN_ALERT "pwm_off(): ioremap failed\n");
return -1;
}
if (sc == 1)
pwm_dev->gpt.tclr |= GPT_TCLR_SCPWM;
else
pwm_dev->gpt.tclr &= ~GPT_TCLR_SCPWM;
iowrite32(pwm_dev->gpt.tclr, base + GPT_TCLR);
iounmap(base);
return 0;
}
static int prescale(struct pwm_dev *pwm_dev, int div)
{
void __iomem *base;
int i = 0;
base = ioremap(pwm_dev->gpt.gpt_base, GPT_REGS_PAGE_SIZE);
if (!base) {
printk(KERN_ALERT "pwm_off(): ioremap failed\n");
return -1;
}
while (div > 2) {
i++;
div /= 2;
}
pwm_dev->gpt.tclr |= GPT_TCLR_PRE; //enable prescaler
pwm_dev->gpt.tclr &= i << 2; //set prescaler ratio
iowrite32(pwm_dev->gpt.tclr, base + GPT_TCLR);
iounmap(base);
return 0;
}
static int set_duty_cycle(struct pwm_dev *pwm_dev, unsigned int duty_cycle)
{
unsigned int new_tmar;
pwm_off(pwm_dev);
if (duty_cycle == 0)
return 0;
new_tmar = (duty_cycle * pwm_dev->gpt.num_freqs) / 100;
if (new_tmar < 1)
new_tmar = 1;
else if (new_tmar > pwm_dev->gpt.num_freqs)
new_tmar = pwm_dev->gpt.num_freqs;
pwm_dev->gpt.tmar = pwm_dev->gpt.tldr + new_tmar;
printk("TMAR : 0x%08x\n", pwm_dev->gpt.tmar);
return pwm_on(pwm_dev);
}
static ssize_t pwm_read(struct file *filp, char __user *buff, size_t count,
loff_t *offp)
{
size_t len;
unsigned int duty_cycle;
ssize_t error = 0;
struct pwm_dev *pwm_dev = (struct pwm_dev *)filp->private_data;
if (!buff)
return -EFAULT;
/* tell the user there is no more */
if (*offp > 0)
return 0;
if (down_interruptible(&pwm_dev->sem))
return -ERESTARTSYS;
if (pwm_dev->gpt.tclr & GPT_TCLR_ST) {
duty_cycle = (100 * (pwm_dev->gpt.tmar - pwm_dev->gpt.tldr))
/ pwm_dev->gpt.num_freqs;
snprintf(pwm_dev->user_buff, USER_BUFF_SIZE,
"PWM%d Frequency %u Hz Duty Cycle %u%%\n",
pwm_dev->gpt.timer_num, pwm_dev->frequency, duty_cycle);
}
else {
snprintf(pwm_dev->user_buff, USER_BUFF_SIZE,
"PWM%d Frequency %u Hz Stopped\n",
pwm_dev->gpt.timer_num, pwm_dev->frequency);
}
len = strlen(pwm_dev->user_buff);
if (len + 1 < count)
count = len + 1;
if (copy_to_user(buff, pwm_dev->user_buff, count)) {
printk(KERN_ALERT "pwm_read(): copy_to_user() failed\n");
error = -EFAULT;
}
else {
*offp += count;
error = count;
}
up(&pwm_dev->sem);
return error;
}
static ssize_t pwm_write(struct file *filp, const char __user *buff,
size_t count, loff_t *offp)
{
size_t len;
unsigned int duty_cycle;
ssize_t error = 0;
struct pwm_dev *pwm_dev = (struct pwm_dev *)filp->private_data;
if (down_interruptible(&pwm_dev->sem))
return -ERESTARTSYS;
if (!buff || count < 1) {
printk(KERN_ALERT "pwm_write(): input check failed\n");
error = -EFAULT;
goto pwm_write_done;
}
/* we are only expecting a small integer, ignore anything else */
if (count > 8)
len = 8;
else
len = count;
memset(pwm_dev->user_buff, 0, 16);
if (copy_from_user(pwm_dev->user_buff, buff, len)) {
printk(KERN_ALERT "pwm_write(): copy_from_user() failed\n");
error = -EFAULT;
goto pwm_write_done;
}
if(pwm_dev->user_buff[0] == '+') {
pwm_off(pwm_dev);
if(pwm_dev->user_buff[1] != '\0')
pwm_dev->gpt.tmar += simple_strtoul(&pwm_dev->user_buff[1], NULL, 0);
pwm_on(pwm_dev);
printk("TMAR : 0x%08x\n", pwm_dev->gpt.tmar);
} else if(pwm_dev->user_buff[0] == '-') {
pwm_off(pwm_dev);
if(pwm_dev->user_buff[1] != '\0')
pwm_dev->gpt.tmar -= simple_strtoul(&pwm_dev->user_buff[1], NULL, 0);
pwm_on(pwm_dev);
printk("TMAR : 0x%08x\n", pwm_dev->gpt.tmar);
} else {
duty_cycle = simple_strtoul(pwm_dev->user_buff, NULL, 0);
set_duty_cycle(pwm_dev, duty_cycle);
}
/* pretend we ate it all */
*offp += count;
error = count;
pwm_write_done:
up(&pwm_dev->sem);
return error;
}
static int pwm_open(struct inode *inode, struct file *filp)
{
int error = 0;
struct pwm_dev *pwm_dev = 0;
unsigned int minor = iminor(inode);
switch(minor) {
case 9: pwm_dev = &pwm9_dev;
break;
case 10: pwm_dev = &pwm10_dev;
break;
case 11: pwm_dev = &pwm11_dev;
break;
}
if(pwm_dev == 0)
return -EFAULT;
filp->private_data = pwm_dev;
if (down_interruptible(&pwm_dev->sem))
return -ERESTARTSYS;
if (pwm_dev->gpt.old_mux == 0) {
if (init_mux(pwm_dev))
error = -EIO;
else if (set_pwm_frequency(pwm_dev, defaultFrequency))
error = -EIO;
}
if (!pwm_dev->user_buff) {
pwm_dev->user_buff = kmalloc(USER_BUFF_SIZE, GFP_KERNEL);
if (!pwm_dev->user_buff)
error = -ENOMEM;
}
up(&pwm_dev->sem);
return error;
}
int pwm_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
int retval = 0;
struct pwm_dev *pwm_dev = (struct pwm_dev *)filp->private_data;
/*
* extract the type and number bitfields, and don't decode
* wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()
*/
if (_IOC_TYPE(cmd) != PWM_IOC_MAGIC)
return -ENOTTY;
if (_IOC_NR(cmd) > PWM_IOC_MAXNR)
return -ENOTTY;
switch (cmd) {
case PWM_ON:
if (pwm_on(pwm_dev))
retval = -EIO;
break;
case PWM_OFF:
if (pwm_off(pwm_dev))
retval = -EIO;
break;
case PWM_SET_DUTYCYCLE:
if (set_duty_cycle(pwm_dev, arg))
retval = -EIO;
break;
case PWM_GET_DUTYCYCLE:
if (pwm_dev->gpt.tclr & GPT_TCLR_ST) { //PWM is on
retval = (100 * (pwm_dev->gpt.tmar - pwm_dev->gpt.tldr))
/ pwm_dev->gpt.num_freqs; //real duty cycle
} else {
printk(KERN_ALERT "PWM%d is OFF\n", pwm_dev->gpt.timer_num);
retval = -EIO;
}
break;
case PWM_SET_FREQUENCY:
if (set_pwm_frequency(pwm_dev, arg))
retval = -EIO;
break;
case PWM_GET_FREQUENCY:
retval = pwm_dev->frequency;
break;
case PWM_SET_POLARITY:
if (scpwm(pwm_dev, arg))
retval = -EIO;
break;
case PWM_SET_CLK:
/* Do no change clock source !!! */
/*
if (pwm_dev->gpt.timer_num == 9) {
printk(KERN_ALERT "Only 32K clk can be used with GPT9\n");
retval = -EIO;
} else {
if (arg == 1)
pwm_dev->gpt.input_freq = CLK_13K_FREQ;
else
pwm_dev->gpt.input_freq = CLK_32K_FREQ;
}
*/
break;
case PWM_SET_PRE:
if (prescale(pwm_dev, arg))
retval = -EIO;
break;
case PWM_PLUS_DUTYCYCLE:
pwm_off(pwm_dev);
pwm_dev->gpt.tmar++;
pwm_on(pwm_dev);
break;
case PWM_MINUS_DUTYCYCLE:
pwm_off(pwm_dev);
if(pwm_dev->gpt.tmar > 0)
pwm_dev->gpt.tmar--;
pwm_on(pwm_dev);
break;
default: /* redundant, as cmd was checked against MAXNR */
return -ENOTTY;
}
return retval;
}
static struct file_operations pwm_fops = {
.owner = THIS_MODULE,
.read = pwm_read,
.write = pwm_write,
.open = pwm_open,
.ioctl = pwm_ioctl,
};
static int __init pwm_init_cdev(void)
{
int error;
error = alloc_chrdev_region(&devt, 9, 3, "pwm"); /* minor number start from 9, count 3*/
if (error < 0) {
printk(KERN_ALERT "alloc_chrdev_region() failed: %d \n",
error);
return -1;
}
cdev_init(&cdev, &pwm_fops);
cdev.owner = THIS_MODULE;
error = cdev_add(&cdev, devt, 3);
if (error) {
printk(KERN_ALERT "cdev_add() failed: %d\n", error);
unregister_chrdev_region(devt, 3);
return -1;
}
return 0;
}
static int __init pwm_init(void)
{
memset(&pwm9_dev, 0, sizeof(struct pwm_dev));
/* change these 4 values to use a different PWM */
pwm9_dev.frequency = defaultFrequency;
pwm9_dev.gpt.timer_num = 9;
pwm9_dev.gpt.mux_offset = GPT9_MUX_OFFSET;
pwm9_dev.gpt.gpt_base = PWM9_CTL_BASE;
pwm9_dev.gpt.input_freq = CLK_SYS_FREQ; /* GPT9 can only use 13MHz clock source */
pwm9_dev.gpt.tldr = 0xFFFFFFFF - (pwm9_dev.gpt.input_freq / pwm9_dev.frequency) + 1;
pwm9_dev.gpt.tmar = 0xFFFFFFFF - ((0xFFFFFFFF - (pwm9_dev.gpt.tldr + 1)) / 2);
pwm9_dev.gpt.tclr = DEFAULT_TCLR;
sema_init(&pwm9_dev.sem, 1);
memset(&pwm10_dev, 0, sizeof(struct pwm_dev));
/* change these 4 values to use a different PWM */
pwm10_dev.frequency = defaultFrequency;
pwm10_dev.gpt.timer_num = 10;
pwm10_dev.gpt.mux_offset = GPT10_MUX_OFFSET;
pwm10_dev.gpt.gpt_base = PWM10_CTL_BASE;
pwm10_dev.gpt.input_freq = CLK_32K_FREQ;
pwm10_dev.gpt.tldr = 0xFFFFFFFF - (pwm10_dev.gpt.input_freq / pwm10_dev.frequency) + 1;
pwm10_dev.gpt.tmar = 0xFFFFFFFF - ((0xFFFFFFFF - (pwm10_dev.gpt.tldr + 1)) / 2);
pwm10_dev.gpt.tclr = DEFAULT_TCLR;
sema_init(&pwm10_dev.sem, 1);
memset(&pwm11_dev, 0, sizeof(struct pwm_dev));
/* change these 4 values to use a different PWM */
pwm11_dev.frequency = defaultFrequency;
pwm11_dev.gpt.timer_num = 11;
pwm11_dev.gpt.mux_offset = GPT11_MUX_OFFSET;
pwm11_dev.gpt.gpt_base = PWM11_CTL_BASE;
pwm11_dev.gpt.input_freq = CLK_32K_FREQ;
pwm11_dev.gpt.tldr = 0xFFFFFFFF - (pwm11_dev.gpt.input_freq / pwm11_dev.frequency) + 1;
pwm11_dev.gpt.tmar = 0xFFFFFFFF - ((0xFFFFFFFF - (pwm11_dev.gpt.tldr + 1)) / 2);
pwm11_dev.gpt.tclr = DEFAULT_TCLR;
sema_init(&pwm11_dev.sem, 1);
if (pwm_init_cdev())
goto init_fail;
printk(KERN_INFO "OMAP3 PWM: character device initialized (major=%d)\n", MAJOR(devt));
return 0;
init_fail:
return -1;
}
module_init(pwm_init);
static void __exit pwm_exit(void)
{
cdev_del(&cdev);
pwm_off(&pwm9_dev);
restore_mux(&pwm9_dev);
if (pwm9_dev.user_buff)
kfree(pwm9_dev.user_buff);
pwm_off(&pwm10_dev);
restore_mux(&pwm10_dev);
if (pwm10_dev.user_buff)
kfree(pwm10_dev.user_buff);
pwm_off(&pwm11_dev);
restore_mux(&pwm11_dev);
if (pwm11_dev.user_buff)
kfree(pwm11_dev.user_buff);
unregister_chrdev_region(devt, 3);
}
module_exit(pwm_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Scott Ellis - Jumpnow");
MODULE_AUTHOR("Steve Chang");
MODULE_DESCRIPTION("PWM example for Gumstix Overo");
2011年1月12日 星期三
Embedded Linux software upgrade with initramfs (1)
1.源由限制
由於有限的memory及flash空間,Software upgrade一直是embedded system不太好處理的一塊.
一般的Linux base Wifi router通常只有16MBytes甚至8MBytes memory而flash大小通常是memory的一半.
系統在正常運作的狀況下kernel & applications往往已經用掉的4MBytes以上.如果是功能更多的裝置還有可能使用更多的memory.
在這樣的狀況下upgrade 是有疑慮的,無法保證系統有足夠的memory來進行.
更新正在運作中的系統是危險的行為.
試想更新正在執行的applicatins或libraries會發生什麼事?
甚至是想要複寫整個已經掛載(mount)的mtd block?
2.網路環境
Upgrade一般需要透過網路取得upgrade image因此必須啟動網路功能.
Upgrade也可以在bootloader中執行,但只限於單純的網路環境,例如Static IP \ DHCP.
若是VLAN 或 IEEE802.1X 的網路環境bootloader就無法正確設定網路.
下載upgrade image的動作最好還是在Linux下執行.
3.版本檢查的時機與方式
系統需要自行檢查伺服器上是否有更新的版本.
太頻繁的檢查會造成無謂的網路頻寬損耗,因此適當時間即可.
檢查更新版本若都必須下載整個upgrade image將造成巨大的頻寬損耗.
比較好的方式是下載一個簡短描述upgrade image的檔案用以檢查是否需要更新.
4.Upgrade與initramfs應用
關於initramfs技術細節請參考以下
http://blog.linux.org.tw/~jserv/archives/001954.html
initramfs 的特性
early user space :
在實際的user space applications啟動前作upgrade檢查及更新動作有幾個好處.
一,這時已經能掛載(mount) mtd block取得設定檔進行網路設定,之後可馬上卸載(umount).
二,系統未掛載任何mtd block因此能直接覆寫整塊mtd block.
三,系統還未執行user space applications因此可使用memory是比較多的而且size是可預期的.
由於有限的memory及flash空間,Software upgrade一直是embedded system不太好處理的一塊.
一般的Linux base Wifi router通常只有16MBytes甚至8MBytes memory而flash大小通常是memory的一半.
系統在正常運作的狀況下kernel & applications往往已經用掉的4MBytes以上.如果是功能更多的裝置還有可能使用更多的memory.
在這樣的狀況下upgrade 是有疑慮的,無法保證系統有足夠的memory來進行.
更新正在運作中的系統是危險的行為.
試想更新正在執行的applicatins或libraries會發生什麼事?
甚至是想要複寫整個已經掛載(mount)的mtd block?
2.網路環境
Upgrade一般需要透過網路取得upgrade image因此必須啟動網路功能.
Upgrade也可以在bootloader中執行,但只限於單純的網路環境,例如Static IP \ DHCP.
若是VLAN 或 IEEE802.1X 的網路環境bootloader就無法正確設定網路.
下載upgrade image的動作最好還是在Linux下執行.
3.版本檢查的時機與方式
系統需要自行檢查伺服器上是否有更新的版本.
太頻繁的檢查會造成無謂的網路頻寬損耗,因此適當時間即可.
檢查更新版本若都必須下載整個upgrade image將造成巨大的頻寬損耗.
比較好的方式是下載一個簡短描述upgrade image的檔案用以檢查是否需要更新.
4.Upgrade與initramfs應用
關於initramfs技術細節請參考以下
http://blog.linux.org.tw/~jserv/archives/001954.html
initramfs 的特性
early user space :
在實際的user space applications啟動前作upgrade檢查及更新動作有幾個好處.
一,這時已經能掛載(mount) mtd block取得設定檔進行網路設定,之後可馬上卸載(umount).
二,系統未掛載任何mtd block因此能直接覆寫整塊mtd block.
三,系統還未執行user space applications因此可使用memory是比較多的而且size是可預期的.
訂閱:
文章 (Atom)