- Autoconf Manual
글 혹은 그림의 출처가 문제있다면 수정 및 삭제하겠습니다. 우측의 Tags 와 검색기능을 이용하여 편하게 찾을 수 있습니다.
Please check buttons in right like tags and language if can't read this blog
2/28/2016
autoconf automake aclocal, autoheader,
최근들어 Autoconf와 Automake 및 관련사항을 잘 다루지 않으며, 거의 사실 사용할 일이 없어, 아래와 같이 Link만 연결한다.
2/27/2016
Linux RC Script 와 /etc/network/interfaces 분석
Linux Init Script로 배포하는 곳마다 다르며, 지속적으로 변화 중인 것 같아 간단히 기록한다.
아래와 같이 간단히 동작부분을 확인만 하자
http://dietpc.org/downloads/source/common/diet-pc/initscript/etc/rc
아래와 같이 간단히 동작부분을 확인만 하자
#! /bin/sh ## # DIET-PC master initialisation script # Copyright (C) 2002-2013 Paul A Whittaker# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA [ -f /etc/profile ] && . /etc/profile export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin umask 022 notify () { # To aid degugging, you might wish to uncomment the sleep command, to give # you a chance to press the key and see errors before they scroll # off. #busybox sleep 3 echo -e "${HL_ON}$*${HL_OFF}" case "$HAVE_SPLASH" in TRUE) ## 숫자변수를 1씩 증가 NOTIFY_COUNT=$(($NOTIFY_COUNT + 1)) echo "show $((65535 * $NOTIFY_COUNT / $NOTIFY_TOTAL))" >>/proc/splash ;; esac } busybox mount /proc # If the console is a VT, we can use ANSI escapes to do highlighting. "tty" # doesn't work until /dev is mounted, so use console=xxx in /proc/cmdline to # determine this. case "`busybox sed -e 's/^.*\ ' /etc/rc /etc/rc.d/* /usr/etc/rc.d/* /usr/local/etc/rc.d/* | busybox wc -l`-1)) else HAVE_SPLASH= fi notify 'Mounting core filesystems' ROOTDEV=`busybox sed -e 's/^.*\ '; then # If root is read-only and it is not prohibited by a "no_root_union" # kernel parameter, try to mount a new root as a union of the original # (read-only) root filesystem and a tmpfs (read-write) filesystem. busybox mkdir -m 0755 /tmp/.overlay busybox modprobe -q unionfs busybox grep -qv '\ ' /proc/cmdline && busybox mount \ -t unionfs -o dirs=/tmp/.overlay=rw:/=ro none /mnt ## if [ $? -eq 0 ]; then cd /mnt busybox pivot_root . ./oldroot busybox umount /oldroot/proc 2>/dev/null busybox mount /proc else # If not mounted already (via a kernel feature), mount a writable # tmpfs /dev. busybox awk 'BEGIN {n=0} $2 == "/dev" {n=1} END {exit n}' \ /proc/mounts && busybox mount -t tmpfs -o \ nr_blocks=256,nr_inodes=1024,mode=0755 none /dev # If the root filesystem is still read-only, try to remount it # read-write. Remounts don't seem to work reliably when using the # Busybox mount applet, so only use it as a last resort. mount -o remount,rw / 2>/dev/null || busybox mount -o remount,rw / if [ $? -ne 0 ]; then # If still no-go, there is no point in continuing - let the # operator try to fix it and then reboot. echo 'Root filesystem is not writable, please fix!' [ "$LOCKDOWN" ] && busybox sleep 10 || busybox sulogin exec reboot -ifd fi fi fi fi busybox mount /sys 2>/dev/null busybox mkdir -p /dev/pts busybox mount /dev/pts 2>/dev/null busybox mkdir -p /dev/shm busybox mount /dev/shm 2>/dev/null notify 'Initializing busybox' busybox --install -s # Remove any residual junk from /var/run. rm -f /var/run/* 2>/dev/null notify 'Initializing /dev' ln -sf "$ROOTDEV" /dev/root 2>/dev/null ln -snf /proc/self/fd /dev/fd ln -sf /proc/self/fd/0 /dev/stdin ln -sf /proc/self/fd/1 /dev/stdout ln -sf /proc/self/fd/2 /dev/stderr ln -sf /proc/kcore /dev/core echo '/sbin/mdev' >/proc/sys/kernel/hotplug mdev -s if [ "$LOCKDOWN" ]; then # Remove root's password hash, thereby preventing root login and su to root. sed -i -e 's/^root:[^:]\+:/root:*:/' /etc/shadow # Turn off console login. sed -i -e '/^logn:/d' /etc/inittab kill -HUP 1 # Set TCP wrappers to deny by default. echo 'ALL: ALL' >/etc/hosts.deny # Remove the setuid bit from busybox, to prevent use of setuid-root applets. chmod u-s /bin/busybox # Prevent unprivileged users from running an X11 terminal emulator. XTERM=`which xterm` [ "$XTERM" ] && chmod 700 "$XTERM" fi notify 'Initializing modules' mkdir -p /lib/modules/`uname -r` depmod -a # If an eth0 hint has been provided via the boot loader or via # /etc/modprobe.conf, use it now, in case there are multiple PCI NICs. [ "$eth0" ] && modprobe -q `echo $eth0 | tr , ' '` modprobe -q eth0 # Forceload some difficult modules that will otherwise neither coldplug nor # hotplug. modprobe -q parport modprobe -q ppp modprobe -q tun modprobe -q floppy modprobe -q loop # Coldplug all platform, PCI, PCMCIA and USB devices initially found (in that # order). for BUS in platform pci pcmcia usb; do if [ -d /sys/bus/$BUS/devices ]; then notify "Initializing $BUS devices" cat /sys/bus/$BUS/devices/*/modalias 2>/dev/null | while read MODULE; \ do modprobe -q $MODULE done fi done # Some last resorts, needed only in the event that bus coldplugging has not # initialised the necessary device. modprobe -q ide-generic modprobe -q scsi_hostadapter modprobe -q sound-slot-0 # Attempt to mount the legacy usb device filesystem if a USB host controller is # now online. mount /proc/bus/usb 2>/dev/null # Set a provisional hostname. if [ "`hostname`" = '(none)' ]; then # First try the contents of /etc/hostname, then the name of the special # non-localhost loopback address. HN=`cat /etc/hostname 2>/dev/null` || HN=`checkhostname -n 127.0.1.1` # Failing that, check all local MAC addresses against /etc/ethers. If # there is a match, set the hostname from the hostname field of the first # matching entry. if [ $? -ne 0 -a -f /etc/ethers ]; then HN=`/sbin/ifconfig -a | awk 'BEGIN {printf "{IGNORECASE=1}\n"} \ /HWaddr/ {printf "$1 == \"%s\" {print $2; exit}\n", $NF}' | \ awk -f - /etc/ethers` fi # As a last resort, derive a hostname from the MAC address of a local # network interface. [ "$HN" ] || HN=`ifconfig -a | awk '/HWaddr/ {printf "X%s\n", $NF; exit}' \ | tr -d :` # Use what we have. [ "$HN" ] && hostname "$HN" fi #### ## 아래의 Shell script는 /etc/network를 자동으로 proc를 정보기반으로 생성해준다. ## /etc/network 와 /etc/network/if-up.d 비롯하여 관련 directory 생성 ## /proc/net/dev 정보를 바탕으로 IFACE (e.g eth0) 를 얻어 IFMETHOD 값을 설정 ## notify 'Initializing network' mkdir -p /etc/network (cd /etc/network; mkdir -p if-up.d if-down.d if-pre-up.d if-post-down.d) if [ ! -f /etc/network/interfaces ]; then notify 'Network not configured - using DHCP' tail -n +3 /proc/net/dev | cut -f1 -d: | while read IFACE; do case "$IFACE" in lo) IFMETHOD='loopback' ;; sit*) IFMETHOD='manual' ;; *) IFMETHOD='dhcp' ;; esac echo "auto $IFACE" >>/etc/network/interfaces echo "iface $IFACE inet $IFMETHOD" >>/etc/network/interfaces done fi ifup -a if [ -x /bin/ifplugd -a -x /etc/ifplugd/ifplugd.action ]; then for IFACE in `netstat -r | awk '/^[0-9]/ {print $NF}'`; do ifplugd -i "$IFACE" -p -q done fi if [ ! -s /etc/hosts.allow ]; then # In the absence of an explicit configuration, set TCP wrappers to grant # access to clients on any local subnet or with the same DNS domain name # suffix. ifconfig | grep '\ >/etc/hosts.allow NETWORK= eval `ipcalc -n $ADDR 2>/dev/null` [ "$NETWORK" ] && echo "ALL: $NETWORK/$MASK" >>/etc/hosts.allow done fi # Check reverse lookups on all active non-loopback interfaces (now that we # (possibly) have DNS). HN= for IPADDR in `ifconfig | grep 'inet addr:[0-9.]\+' | sed -e \ 's/^.*inet addr:\([0-9.]\+\).*$/\1/' | grep -v '^127\.'`; do HN=`checkhostname -n "$IPADDR" | cut -f1 -d.` [ "$HN" ] && break done if [ "$HN" ]; then # Any hostname found via reverse lookup will be considered more # authoritative than the provisional hostname (N.B. a hostname set by # /sbin/udhcpc-helper from DHCP results is provisional). If you don't # want this behaviour, comment out everything except the "else" clause of # this "if" statement (including if, else, and fi lines). hostname "$HN" else # If there is no better hostname, endorse the provisional one by adding # an /etc/hosts entry for it using a local IP address. sed -i -e '/\<'"`hostname`"\$/d /etc/hosts echo -e "${IPADDR:-127.0.1.1}\t`hostname`" >>/etc/hosts fi # If possible, set the system clock at this point. Fsck needs this for # scheduled checks, and loggers need it for meaningful timestamps. Change -u # to -l if you want your system clock to keep local time rather than UTC time. # NTP synchronisation might be slow, but we can't background this, as it might # be our last hope of getting a plausible clock setting (before fsck etc). if [ -c /dev/rtc ]; then notify 'Setting time from hardware clock' if [ "`hwclock -u -r | egrep -w '(1970|2000)'`" ]; then notify 'Sanity check failed - ignoring data from hardware clock' else hwclock -u -s fi if checkhostname -q ${timeserver:-timeserver}; then notify 'Synchronising clock with network time server' ntpd -n -q -p ${timeserver:-timeserver} hwclock -u -w ntpd -p ${timeserver:-timeserver} fi fi notify 'Mounting all filesystems' # We might have portmap (IPV4 only) or rpcbind (IPV4+IPV6) or neither. portmap 2>/dev/null || rpcbind 2>/dev/null || true # If you reference a network block device (/dev/nbd0 etc al) in /etc/fstab, # you must prepare it for use here, e.g. #nbd-client myserver 2000 /dev/nbd0 -persist >/dev/null 2>&1 # Scan for RAID arrays and try to assemble all that are found. Only start # fully intact arrays. if [ "`which mdadm`" ]; then if [ ! -e /etc/mdadm.conf ]; then echo 'MAILADDR root' >/etc/mdadm.conf mdadm --examine --brief --scan --config=partitions >>/etc/mdadm.conf fi mdadm --assemble --scan --no-degraded --auto=yes mdadm --monitor --scan --daemonise --pid-file=/var/run/mdmonitor.pid fi # Scan for LVM volume groups and activate all that are found. if [ "`which lvm`" ]; then rm -f /etc/lvm/cache/.cache lvm pvscan lvm vgscan lvm vgchange -ay fi fsck -aCRAT case $? in 0|1) ;; 2|3) exec reboot -ifd ;; *) echo 'Fsck failed ... need help!' [ "$LOCKDOWN" ] && sleep 10 || sulogin exec reboot -ifd ;; esac mount -a 2>/dev/null if [ $? -ne 0 ]; then # The kernel might have been too slow to load the necessary modules during # the first attempt, so wait a moment and then retry. sleep 2 mount -a 2>/dev/null fi swapon -a 2>/dev/null # Logging chews up a little memory but is a valuable debugging aid. notify 'Starting loggers' if checkhostname -q ${logserver:-logserver}; then syslogd -m 0 -R ${logserver:-logserver} else syslogd -m 0 -C fi klogd # Start crond (if available). if [ -x /sbin/crond ]; then notify 'Starting cron' mkdir -p /var/spool/cron/crontabs chmod 1733 /var/spool/cron/crontabs crond fi notify 'Starting power management' # If CPU frequency scaling is available, install a demand-driven governor # to reduce power consumption and heat output when high CPU performance is not # needed. for CPU in /sys/devices/system/cpu/cpu*; do if [ -f $CPU/cpufreq/scaling_governor ]; then echo 'conservative' >$CPU/cpufreq/scaling_governor 2>/dev/null if [ "`cat $CPU/cpufreq/scaling_governor`" != 'conservative' ]; then echo 'ondemand' >$CPU/cpufreq/scaling_governor 2>/dev/null fi fi done # Set a 30 minute idle spin-down on all hard disks. for DISK in /dev/hd? /dev/sd?; do [ "$DISK" = 'hd?' -o "$DISK" = 'sd?' ] && continue hdparm -S 241 $DISK >/dev/null 2>&1 done if [ -f /etc/sysctl.conf ]; then notify 'Adjusting kernel parameters' sysctl -e -p fi # If you want to force canonicalization of files in /usr/etc or /usr/local/etc, # uncomment the following "if". This will delete everything in /etc that # previously got copied from /usr/etc and /usr/local/etc, and thereby force # them to be copied again. This is the only way to ensure that package removal # doesn't leave config file remnants, but may prove very confusing to users, # who will most likely expect the /etc copies to be authoritative and # persistent. #if [ -s /etc/shadowfiles ]; then # ( # cd /etc # sed -e "s/'/'\"'\"'/g" -e "s/^/rm -f '/" -e "s/\$/'/" shadowfiles | sh # ) #fi # Since packages installed in /usr and /usr/local can't directly own files in # /etc, we will non-destructively merge /usr/etc and /usr/local/etc into /etc. # If the root filesystem is persistent or has a persistent layer, pre-existing # copies in /etc will supercede the installation defaults in /usr[/etc]. # Otherwise, changes will be lost when the system is rebooted, and permanent # changes can only occur by modifiying the /usr/[local/]etc master copies. for PKG_ROOT in /usr /usr/local; do if [ -d $PKG_ROOT/etc ]; then ( cd $PKG_ROOT/etc find . -type f -print find . -print | cpio -d -p /etc 2>/dev/null ) fi done > /etc/shadowfiles # Initialise optional packages. # # Rather than executing rc.d files (which would have significant fork and exec # overheads), we source them and run the functions and/or aliases they define. # This is fast, but also fragile, because a syntax error in any rc.d file will # kill this script. On a persistent root filesystem, we have no way of knowing # whether or not configure actions have already occurred, so the rc.d scripts # must be "replay-safe" and should avoid unnecessary reconfiguration. ls /etc/rc.d | while read SVC; do . /etc/rc.d/$SVC eval ${SVC}_configure logger -t 'rc' -p daemon.info "$SVC configured" eval ${SVC}_start logger -t 'rc' -p daemon.info "$SVC started" done # Display an active interface summary just before the login prompt appears, so # that the IP address(es) in use remain visible on the console as long as # possible. ifconfig | awk 'BEGIN {i=""} $0 !~ /^[[:blank:]]/ && $0 != "" {i=$1} $2 ~ /^addr:/ {print i; print $0}' [ "$HAVE_SPLASH" ] && echo 'show 65535' >>/proc/splash
http://dietpc.org/downloads/source/common/diet-pc/initscript/etc/rc
2/26/2016
Audio-ALSA Playback & Capture Flow
1. ALSA의 기본 API
DM368은 TI에서 제공하는 Audio Guide는 없지만 구조는 거의 동일하다.
TI 제공하는 Audio는 기본 구조는 동일하지만, CPU에따라 EVM에 따라 조금씩 다르다.
하지만, OMAP인 경우 기본구조와 다르게 Audio 구조가 복잡하지만, 요즘은 거의 다 ALSA로 기반으로 하므로 아래와 같이 ALSA의 API들을 알아두록하자.
관련내용출처
DM368은 TI에서 제공하는 Audio Guide는 없지만 구조는 거의 동일하다.
TI 제공하는 Audio는 기본 구조는 동일하지만, CPU에따라 EVM에 따라 조금씩 다르다.
하지만, OMAP인 경우 기본구조와 다르게 Audio 구조가 복잡하지만, 요즘은 거의 다 ALSA로 기반으로 하므로 아래와 같이 ALSA의 API들을 알아두록하자.
- Audio 관련 부분 전체 Index
TI에서 제공해주는 Audio 관련 ALSA Guide로 현재 AM38xxx 와 DM84xx 를 위해서 변경사항이 있는지 확인만 하자
- ALSA Common API
관련 세부내용들은 생략하도록 하겠다.
ALSA를 이용하여 기본적으로 Playback하는 flow로 그리 어렵지 않으며 거의 다른 일반 Linux System Call과 거의 유사하다.
Name | Description |
---|---|
snd_pcm_open | Opens a PCM stream |
snd_pcm_close | Closes a previously opened PCM stream |
snd_pcm_hw_params_any | Fill params with a full configuration space for a PCM |
snd_pcm_hw_params_test_ < | Test the availability of important parameters like number of channels, sample rate etc. For e.g. snd_pcm_hw_params_test_format, snd_pcm_hw_params_test_rate etc. |
snd_pcm_hw_params_set_ < | Set the different configuration parameters. For e.g. snd_pcm_hw_params_set_format, snd_pcm_hw_params_set_rate etc. |
snd_pcm_hw_params | Install one PCM hardware configuration chosen from a configuration space |
snd_pcm_writei | Write interleaved frames to a PCM |
snd_pcm_readi | Read interleaved frames from a PCM |
snd_pcm_prepare | Prepare PCM for use |
snd_pcm_drop | Stop a PCM dropping pending frames |
snd_pcm_drain | Stop a PCM preserving pending frames |
아래의 ALSA의 Playback or Capture도 간단하게 짜기 싫다면, ALSA Tool을 간단하게 이용하도록하자.
1.1 ALSA의 PLAYBACK FLOW
- Playback Mode로 Open
- hw parameter 관련설정 (format/acess type/ sample rate/ channel )
- write로 재생시작
1.2 ALSA 의 CAPTURE FLOW
상위와 동일
- Capture Mode로 Open
- hw parameter 관련설정 (format/acess type/ sample rate/ channel )
- read로 녹음시작
관련내용출처
2/25/2016
Linux Network 설정
1. Linux Network 설정
이부분의 동작방식은 다시 boot script 부분을 보면 동작하는 방식을 이해가능
http://dis.um.es/~lopezquesada/documentos/IES_1213/SAD/curso/UT8/interfaces.pdf
http://www.cyberciti.biz/faq/setting-up-an-network-interfaces-file/
이부분의 동작방식은 다시 boot script 부분을 보면 동작하는 방식을 이해가능
- /etc/network/interfaces 설정의 예제
http://dis.um.es/~lopezquesada/documentos/IES_1213/SAD/curso/UT8/interfaces.pdf
http://www.cyberciti.biz/faq/setting-up-an-network-interfaces-file/
- 나의 Network 설정 (/etc/network/interfaces)
# Wired or wireless interfaces auto eth0 iface eth0 inet dhcp pre-up /bin/grep -v -e "ip=[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+" /proc/cmdline > /dev/null
$ cat /etc/network/interfaces # /etc/network/interfaces -- configuration file for ifup(8), ifdown(8) # The loopback interface auto lo iface lo inet loopback # Wireless interfaces # # Example of an unencrypted (no WEP or WPA) wireless connection # that connects to any available access point: # iface wlan0 inet dhcp wireless_mode managed wireless_essid any # # # Same as above but locked to a specific access point: # #iface wlan0 inet dhcp # wireless_mode managed # wireless-essid some-essid # # A WEP encrypted connection locked to a specific access point: # #iface wlan0 inet dhcp # wireless-essid some-essid # wireless-key s:My-PlainText-Password # wireless-mode managed # # A WPA1 or WPA2 encrypted connection locked to a specific access point. # This is the best option for non-roaming, single-network usage. # Note that your card may require a firmware update to use WPA. # Some distributions install a temporary volatile firmware update on ifup. # #iface wlan0 inet dhcp # wpa-essid some-essid # wpa-psk My-PlainText-Password # # A WPA1 or WPA2 encrypted connection using an external configuration file # for wpa-supplicant. This is the way to go if you need to configure multiple # networks with different keys and / or WPA settings and roaming support. # # iface wlan0 inet dhcp # wpa-conf /etc/wpa_supplicant.conf # wpa-driver hostap iface atml0 inet dhcp # Wired or wireless interfaces auto eth0 iface eth0 inet static pre-up /bin/grep -v -e "ip=[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+" /proc/cmdline > /dev/null iface eth1 inet dhcp # Ethernet/RNDIS gadget (g_ether) # ... or on host side, usbnet and random hwaddr iface usb0 inet static address 192.168.0.202 netmask 255.255.255.0 network 192.168.0.0 gateway 192.168.0.200 # Zaurus 2.4 Lineo net_fd; obsolete iface usbd0 inet static address 192.168.129.201 netmask 255.255.255.0 network 192.168.129.0 gateway 192.168.129.200 # iPAQ 2.4 mach-sa1100/usb-eth # (192.168.0.202 is the iPAQ's IP, 192.168.0.200 is the host's IP) iface usbf inet static address 192.168.0.202 netmask 255.255.255.0 network 192.168.0.0 gateway 192.168.0.200 # Bluetooth networking iface bnep0 inet dhcp
2/22/2016
Audio-ALSA SOC Framework (Kernel)
1. ALSA KERNEL Driver 전체구성
아래는 DM368 IPNC의 기준으로 보겠으며 다른 SoC로 가면 전체구조가 변경이 될 수도 있겠지만,
아래는 DM368 IPNC의 기준으로 보겠으며 다른 SoC로 가면 전체구조가 변경이 될 수도 있겠지만,
거의 근본적으로 구성은 AP/SoC의 관련 Driver 만들어서 ALSA Interface에 맞게 연결하여 동작하는 구조가 비슷하므로, 관련부분을 알아보도록하자.
http://processors.wiki.ti.com/index.php/Processor_SDK_Linux_Audio
2. ALSA의 SOC 기본 Driver 구조
DM368의 SOC를 세부적으로 본다며, 아래와 같으며, 각 설명 Driver의 구성은 다음과 같다.
2.1 Machine Driver
TI-SOC의 구성 , 아래와 같이 Machine Driver가 기본설정하고 , Platform과 Codec을 연결을 해준다.
정확히 cpu_dai와 codec_dai를 mapping을 하여 동작한다.
2.2 Platform Driver
TI에서 제공하는 Audio Driver McBSP or McASP 이며 이는 EDMA와 연결하여 동작한다.
그리고, 아래와 같이 PCM Driver와 연동이 되어 동작이 된다.
APP에서 PCM을 OPEN할 경우부터 기본설정되는 부분이 아래에 다 들어가 있다.
McBSP가 HW Codec과 연결되어 실질적인 역할하며, Interface는 I2S이지만, 다른 것으로 변경가능하다 (DSP Mode)
2.3 HW Codec Driver
Codec Driver는 구조가 거의 비슷하며, I2C Driver로 Codec을 Control 하게되어 각 설정을 변경하고, 등록을 하는 것이다.
이는 soc_dai를 등록하여 동작하게 한다.
Codec를 동작하게 하기위해서는 미리 I2C Device를 등록을 해야 동작이 가능하다.
(Audio-ALSA SOC Codec Driver 참조)
http://processors.wiki.ti.com/index.php/AM335x_Audio_Driver's_Guide
http://processors.wiki.ti.com/index.php/DM81xx_AM38xx_Audio_Driver_User_Guide
3. ALSA Card 등록 및 확인
DM368인 경우, TLVAIC3x 코덱을 사용을 하면, 2개의 McBSP Driver의 충돌로 인하여 제대로 등록이 되지 않는다.
이중 davinci-i2s.c 선택하여 사용함
User에서는 ALSA만 보면 되니 복잡하지 않지만, Driver 개발자에서는 제법 복잡한 구조이다.
OSS 와 ALSA 전체구조 및 ALSA 설명
TI ALSA Codec Driver 세부구성파악
- 각 디렉토리 구성
sound sound/core/ sound/soc/codecs sound/soc/davinci sound/soc
- 각 디렉토리의 사용되어지는 파일구성
./sound/core/pcm_lib.o ./sound/core/snd-pcm.o ./sound/core/init.o ./sound/core/memory.o ./sound/core/jack.o ./sound/core/sound.o ./sound/core/timer.o ./sound/core/pcm.o ./sound/core/pcm_timer.o ./sound/core/device.o ./sound/core/control.o ./sound/core/pcm_memory.o ./sound/core/misc.o ./sound/core/snd-page-alloc.o ./sound/core/info.o ./sound/core/snd-timer.o ./sound/core/pcm_misc.o ./sound/core/snd.o ./sound/core/memalloc.o ./sound/core/pcm_native.o ./sound/soc/soc-dapm.o ./sound/soc/soc-utils.o ./sound/soc/codecs/tlv320aic3x.o ./sound/soc/codecs/snd-soc-tlv320aic3x.o ./sound/soc/davinci/snd-soc-davinci.o ./sound/soc/davinci/davinci-evm.o ./sound/soc/davinci/davinci-i2s.o ./sound/soc/davinci/davinci-pcm.o ./sound/soc/davinci/snd-soc-davinci-i2s.o ./sound/soc/davinci/snd-soc-evm.o ./sound/soc/soc-core.o ./sound/soc/snd-soc-core.o ./sound/soc/soc-cache.o ./sound/soc/soc-jack.o ./sound/soundcore.o ./sound/sound_core.o ./sound/last.o
- TI에서 제공하는 Audio 관련 부분 설명
http://processors.wiki.ti.com/index.php/Processor_SDK_Linux_Audio
2. ALSA의 SOC 기본 Driver 구조
DM368의 SOC를 세부적으로 본다며, 아래와 같으며, 각 설명 Driver의 구성은 다음과 같다.
- Codec Driver : sound/soc/codecs/tlv320aic3x.c
- Platform Driver: sound/soc/davinci/davinci-i2s.c
- Machine Driver: sound/soc/davinci/davinci-evm.c
- SOC의 기본구조 설명
2.1 Machine Driver
TI-SOC의 구성 , 아래와 같이 Machine Driver가 기본설정하고 , Platform과 Codec을 연결을 해준다.
정확히 cpu_dai와 codec_dai를 mapping을 하여 동작한다.
$ vi sound/soc/davinci/davinci-evm.c #define AUDIO_FORMAT ( SND_SOC_DAIFMT_DSP_A | \ SND_SOC_DAIFMT_CBM_CFM | \ SND_SOC_DAIFMT_IB_NF) static struct snd_soc_dai_link dm365_evm_dai = { #ifdef CONFIG_SND_DM365_AIC3X_CODEC .name = "TLV320AIC3X", .stream_name = "AIC3X", .cpu_dai_name = "davinci-mcbsp", // CPU에서 사용하는 Audio Driver name , sound/soc/davinci/davinci-i2s.c .codec_dai_name = "tlv320aic3x-hifi", // CODEC에서 등록한 SOC DAI 이름 sound/soc/codecs/tlv320aic3x.c .init = evm_aic3x_init, .codec_name = "tlv320aic3x-codec.1-0018", .ops = &evm_ops, #elif defined(CONFIG_SND_DM365_VOICE_CODEC) .name = "Voice Codec - CQ93VC", .stream_name = "CQ93", .cpu_dai_name = "davinci-vcif", .codec_dai_name = "cq93vc-hifi", .codec_name = "cq93vc-codec", #endif .platform_name = "davinci-pcm-audio", // sound/soc/davinci/davinci-pcm.c ( platform driver ) }; /* davinci dm365 evm audio machine driver */ static struct snd_soc_card dm365_snd_soc_card_evm = { // SOC Card 등록 .name = "DaVinci DM365 EVM", .dai_link = &dm365_evm_dai, .num_links = 1, }; static int __init evm_init(void) { ....... } else if (machine_is_davinci_dm365_evm() || machine_is_davinci_dm365_ipnc() || machine_is_davinci_dm368_ipnc()) { evm_snd_dev_data = &dm365_snd_soc_card_evm; index = 0; } evm_snd_device = platform_device_alloc("soc-audio", index); ///sound/soc/soc-core.c 와 연결 if (!evm_snd_device) return -ENOMEM; platform_set_drvdata(evm_snd_device, evm_snd_dev_data); ret = platform_device_add(evm_snd_device); if (ret) platform_device_put(evm_snd_device); .... } module_init(evm_init); // module init 하게 되면 아래 순서 soc_probe -> snd_soc_register_card -> snd_soc_instantiate_cards -> snd_soc_instantiate_card(struct snd_soc_card *card)
- 아래에서 Kernel Log에서 확인 가능
ALSA device list: #0: DaVinci DM365 EVM
2.2 Platform Driver
TI에서 제공하는 Audio Driver McBSP or McASP 이며 이는 EDMA와 연결하여 동작한다.
그리고, 아래와 같이 PCM Driver와 연동이 되어 동작이 된다.
- PCM Driver
APP에서 PCM을 OPEN할 경우부터 기본설정되는 부분이 아래에 다 들어가 있다.
$ vi ./sound/soc/davinci/davinci-pcm.c // PCM Driver로 File 정보를 여기서 처리 그리고, EDMA 처리 등을 담당. static struct snd_pcm_hardware pcm_hardware_playback = { // ALSA의 기본 Playback 관련설정 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), .formats = (SNDRV_PCM_FMTBIT_S16_LE), .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), .formats = (SNDRV_PCM_FMTBIT_S16_LE), .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_KNOT), .rate_min = 8000, .rate_max = 96000, .channels_min = 2, .channels_max = 2, .buffer_bytes_max = 128 * 1024, .period_bytes_min = 32, .period_bytes_max = 8 * 1024, .periods_min = 16, .periods_max = 255, .fifo_size = 0, }; static struct snd_pcm_hardware pcm_hardware_capture = { // ALSA의 기본 Capture 관련설정 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE), .formats = (SNDRV_PCM_FMTBIT_S16_LE), .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_KNOT), .rate_min = 8000, .rate_max = 96000, .channels_min = 2, .channels_max = 2, .buffer_bytes_max = 128 * 1024, .period_bytes_min = 32, .period_bytes_max = 8 * 1024, .periods_min = 16, .periods_max = 255, .fifo_size = 0, }; /* PCM 기본 동작 Driver , PCM OPEN시, HW_PARAM 정보, TRIGGER, 이는 곳 EDMA와 연결을 시킨다. */ static struct snd_pcm_ops davinci_pcm_ops = { .open = davinci_pcm_open, .close = davinci_pcm_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = davinci_pcm_hw_params, //HW_PARAM 설정 , ALSA APP에 호출될 때 호출 . .hw_free = davinci_pcm_hw_free, .prepare = davinci_pcm_prepare, // TI EDMA 준비 .trigger = davinci_pcm_trigger, // TI EDMA Control .pointer = davinci_pcm_pointer, .mmap = davinci_pcm_mmap, // DMA 관련 MMAP }; static struct snd_soc_platform_driver davinci_soc_platform = { .ops = &davinci_pcm_ops, .pcm_new = davinci_pcm_new, .pcm_free = davinci_pcm_free, }; static int __devinit davinci_soc_platform_probe(struct platform_device *pdev) { return snd_soc_register_platform(&pdev->dev, &davinci_soc_platform); } static struct platform_driver davinci_pcm_driver = { .driver = { .name = "davinci-pcm-audio", .owner = THIS_MODULE, }, .probe = davinci_soc_platform_probe, .remove = __devexit_p(davinci_soc_platform_remove), };
- CPU AUDIO Driver
McBSP가 HW Codec과 연결되어 실질적인 역할하며, Interface는 I2S이지만, 다른 것으로 변경가능하다 (DSP Mode)
$ vi ./sound/soc/davinci/davinci-i2s.c //MCBSP의 Main Controller 로, 실제 CPU Dai에 연결된다. static struct snd_soc_dai_ops davinci_i2s_dai_ops = { .startup = davinci_i2s_startup, .shutdown = davinci_i2s_shutdown, .prepare = davinci_i2s_prepare, .trigger = davinci_i2s_trigger, .hw_params = davinci_i2s_hw_params, // HW_PARAM 설정 .set_fmt = davinci_i2s_set_dai_fmt, .set_clkdiv = davinci_i2s_dai_set_clkdiv, }; static struct snd_soc_dai_driver davinci_i2s_dai = { // Capture/Playback I2S Interface의 동작범위 와 Format 정의 .playback = { .channels_min = 2, .channels_max = 2, .rates = DAVINCI_I2S_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, .capture = { .channels_min = 2, .channels_max = 2, .rates = DAVINCI_I2S_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, .ops = &davinci_i2s_dai_ops, }; static int davinci_i2s_probe(struct platform_device *pdev) { ..... EDMA 관련 초기화 ret = snd_soc_register_dai(&pdev->dev, &davinci_i2s_dai); if (ret != 0) goto err_free_mem; } static struct platform_driver davinci_mcbsp_driver = { .probe = davinci_i2s_probe, .remove = davinci_i2s_remove, .driver = { .name = "davinci-mcbsp", .owner = THIS_MODULE, }, }; static int __init davinci_i2s_init(void) { return platform_driver_register(&davinci_mcbsp_driver); } module_init(davinci_i2s_init);
2.3 HW Codec Driver
Codec Driver는 구조가 거의 비슷하며, I2C Driver로 Codec을 Control 하게되어 각 설정을 변경하고, 등록을 하는 것이다.
이는 soc_dai를 등록하여 동작하게 한다.
Codec를 동작하게 하기위해서는 미리 I2C Device를 등록을 해야 동작이 가능하다.
(Audio-ALSA SOC Codec Driver 참조)
$ vi ./sound/soc/codecs/tlv320aic3x.c // Codec Driver 현재 AIC3100으로 변경 중. 서로 호환이 되지 않음
static struct snd_soc_dai_driver aic3x_dai = {
.name = "tlv320aic3x-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
.channels_max = 2,
.rates = AIC3X_RATES,
.formats = AIC3X_FORMATS,},
.capture = {
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = AIC3X_RATES,
.formats = AIC3X_FORMATS,},
.ops = &aic3x_dai_ops,
};
static int aic3x_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
......
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_aic3x, &aic3x_dai, 1);
}
static struct i2c_driver aic3x_i2c_driver = {
.driver = {
.name = "tlv320aic3x-codec",
.owner = THIS_MODULE,
},
.probe = aic3x_i2c_probe,
.remove = aic3x_i2c_remove,
.id_table = aic3x_i2c_id,
};
static inline void aic3x_i2c_init(void)
{
int ret;
ret = i2c_add_driver(&aic3x_i2c_driver);
if (ret) printk(KERN_ERR "%s: error regsitering i2c driver, %d\n", __func__, ret);
}
static int __init aic3x_modinit(void)
{
int ret = 0;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&aic3x_i2c_driver);
if (ret != 0) {
printk(KERN_ERR "Failed to register TLV320AIC3x I2C driver: %d\n",
ret);
}
#endif
return ret;
}
module_init(aic3x_modinit);
- AM335x 와 DM81xx Driver Guide
http://processors.wiki.ti.com/index.php/AM335x_Audio_Driver's_Guide
http://processors.wiki.ti.com/index.php/DM81xx_AM38xx_Audio_Driver_User_Guide
3. ALSA Card 등록 및 확인
- Kernel Log 확인
DM368인 경우, TLVAIC3x 코덱을 사용을 하면, 2개의 McBSP Driver의 충돌로 인하여 제대로 등록이 되지 않는다.
ALSA device list: #0: DaVinci DM365 EVM
- ALSA Card 등록확인
$ vi sound/soc/davinci/davinci-evm.c /* davinci dm365 evm audio machine driver */ static struct snd_soc_card dm365_snd_soc_card_evm = { .name = "DaVinci DM365 EVM", .dai_link = &dm365_evm_dai, .num_links = 1, }; static int __init evm_init(void) { ......... } else if (machine_is_davinci_dm365_evm() || machine_is_davinci_dm365_ipnc() || machine_is_davinci_dm368_ipnc()) { evm_snd_dev_data = &dm365_snd_soc_card_evm; index = 0; } evm_snd_device = platform_device_alloc("soc-audio", index); if (!evm_snd_device) return -ENOMEM; platform_set_drvdata(evm_snd_device, evm_snd_dev_data); ret = platform_device_add(evm_snd_device); if (ret) platform_device_put(evm_snd_device); ........ } module_init(evm_init); module_exit(evm_exit);
- ALSA AUDIO Driver 등록 확인
이중 davinci-i2s.c 선택하여 사용함
- ./sound/soc/davinci/davinci-i2s.c // 이 McBSP는 일반 Codec 사용
- ./arch/arm/mach-davinci/mcbsp.c // 이 McBSP는 Voice Codec을 사용시 사용
$ vi ./arch/arm/mach-davinci/board-dm368-ipnc.c
static struct snd_platform_data dm365_evm_snd_data = {
.asp_chan_q = EVENTQ_3,
};
$ vi ./arch/arm/mach-davinci/dm365.c
static struct resource dm365_asp_resources[] = {
{
.start = DAVINCI_DM365_ASP0_BASE,
.end = DAVINCI_DM365_ASP0_BASE + SZ_8K - 1,
.flags = IORESOURCE_MEM,
},
{
.start = DAVINCI_DMA_ASP0_TX,
.end = DAVINCI_DMA_ASP0_TX,
.flags = IORESOURCE_DMA,
},
{
.start = DAVINCI_DMA_ASP0_RX,
.end = DAVINCI_DMA_ASP0_RX,
.flags = IORESOURCE_DMA,
},
};
static struct platform_device dm365_asp_device = {
.name = "davinci-mcbsp", // 현재 충돌 중. McBSP Driver 가 두 개
.id = -1,
.num_resources = ARRAY_SIZE(dm365_asp_resources),
.resource = dm365_asp_resources,
};
platform_device_register(&dm365_asp_device);
2/21/2016
Eclipse Neon (C/C++) CDT 설치 (개발환경구성-2)
1. Eclipse Neon CDT for Window 설치
이제 최신 Version인 Eclipse Neon을 Window에 설치를 해보자.
Eclipse를 설치 후 본인의 Window의 Program 제거에 등록이 되지는 않는다.
그러므로 관련 PATH를 알아두고 추후 삭제할일 존재한다면 이 PATH를 제거하자
현재 Java로 개발을 진행하지 않기 때문에 Eclipse C/C++ Version 만 설치하기로 결정.
Neon은 Eclipse의 Android 처럼 Version 과 같이 이름이 변경되는 Project 명이라 생각하면되겠다.
https://www.eclipse.org/downloads/
https://eclipse.org/cdt/
1.1 Eclipse Neon 설치시, Java JDK 설치
WIN 64bit : jdk-7u79-windows-x64.exe Download 및 설치
저의문제는 JDK Version 문제 였으나, 아래와 같이 RAM Size 문제일 가능성도 있을 것 같다
-Xms256m
-Xmx1024m
http://dkatlf900.tistory.com/93
1.2 Eclipse CDT 설치 후 화면확인
크로스 컴파일러를 설치가 되어 있어야 제대로된 동작이 가능한 것 같다.
추가설치를 원한다면, Help->Eclipse Market place 에서 설치가능
2. Eclipse 확장
Help->Eclipse Marketplace 로 가면 추가적인 패키지들을 설치를 할수 있다.
이 부분은 자주 확인을 해야하며, 수시로 적용되는 패키지를 확인하자
CCS의 Eclipse 확장
https://ahyuo.blogspot.kr/search/label/Eclipse?updated-max=2016-02-15T01:32:00%2B09:00&max-results=20&start=6&by-date=false
요즘 내가 Python을 사용하다보니, 관련부분 기능 적어놓는다.
Python을 위해 추가 설치
PyDev - Python IDE for Eclipse
http://kaizen8501.tistory.com/16
http://egloos.zum.com/anster/v/2170490
3. Linux용 Eclipse Neon CDT 설치
설치만 해보고 이를 이용하여 빌드를 하지 않았으며, 큰 문제가 없던 걸로 기억한다.
이 방법으로 잘 설정한다면, 모든 작업을 Eclipse에서 가능하겠지만, Window에서 Virtual Box 안에서 Eclipse를 다시 실행하는 것이 싫다.
http://lky1001.tistory.com/71
http://lky1001.tistory.com/68?category=525478
http://janaxelson.com/eclipse5.htm
이제 최신 Version인 Eclipse Neon을 Window에 설치를 해보자.
Eclipse를 설치 후 본인의 Window의 Program 제거에 등록이 되지는 않는다.
그러므로 관련 PATH를 알아두고 추후 삭제할일 존재한다면 이 PATH를 제거하자
현재 Java로 개발을 진행하지 않기 때문에 Eclipse C/C++ Version 만 설치하기로 결정.
Neon은 Eclipse의 Android 처럼 Version 과 같이 이름이 변경되는 Project 명이라 생각하면되겠다.
- Eclipse Neon Dowload
https://www.eclipse.org/downloads/
- Eclipse CDT Download
https://eclipse.org/cdt/
- 관련설치
1.1 Eclipse Neon 설치시, Java JDK 설치
WIN 64bit : jdk-7u79-windows-x64.exe Download 및 설치
- 설치후 문제사항
- 수정사항
저의문제는 JDK Version 문제 였으나, 아래와 같이 RAM Size 문제일 가능성도 있을 것 같다
-Xms256m
-Xmx1024m
http://dkatlf900.tistory.com/93
1.2 Eclipse CDT 설치 후 화면확인
크로스 컴파일러를 설치가 되어 있어야 제대로된 동작이 가능한 것 같다.
- Eclipse 설치 후 확장기능
추가설치를 원한다면, Help->Eclipse Market place 에서 설치가능
2. Eclipse 확장
Help->Eclipse Marketplace 로 가면 추가적인 패키지들을 설치를 할수 있다.
이 부분은 자주 확인을 해야하며, 수시로 적용되는 패키지를 확인하자
CCS의 Eclipse 확장
https://ahyuo.blogspot.kr/search/label/Eclipse?updated-max=2016-02-15T01:32:00%2B09:00&max-results=20&start=6&by-date=false
2.1 Eclipse Neon 추가 설치 (Python)
요즘 내가 Python을 사용하다보니, 관련부분 기능 적어놓는다.
Python을 위해 추가 설치
PyDev - Python IDE for Eclipse
http://kaizen8501.tistory.com/16
http://egloos.zum.com/anster/v/2170490
3. Linux용 Eclipse Neon CDT 설치
설치만 해보고 이를 이용하여 빌드를 하지 않았으며, 큰 문제가 없던 걸로 기억한다.
이 방법으로 잘 설정한다면, 모든 작업을 Eclipse에서 가능하겠지만, Window에서 Virtual Box 안에서 Eclipse를 다시 실행하는 것이 싫다.
http://lky1001.tistory.com/71
http://lky1001.tistory.com/68?category=525478
http://janaxelson.com/eclipse5.htm
2/20/2016
Cygwin 설치 및 Eclipse 을 위한 설정 (개발환경구성-1)
1. Window 용 Linux Package(Cygwin) 설치
Cygwin에 크로스 컴파일러로 Cygwin와 MinGW 존재하며, 이를 설치를 하여 이곳에 설치를 해도 무방하다
윈도우에서 다양한 Linux Tool Package를 사용이 가능하며, 크로스 컴파일러로도 사용하기때문에 이를 설치한다.
현재 나의 경우는 ssh를 이용하여 이클립스와 연동하여 사용하는 것이 주 목적이다.
상위 Cygwin에 MingGW도 포함
http://rinovation.tistory.com/2
https://www.eclipse.org/forums/index.php/t/1073505/
2. Cygwin 설치 및 재설치
Cygwin은 윈도우의 제어판에서 프로그램 제거를 할 수가 없다.
설치시 이부분을 정확하게 인지하고 있어야한다.
setup-x86_64.exe 을 다시 실행하여 필요한 Package를 추가하여 재설치가 가능하다
상위 그림에서 패키지를 제공해주는 사이트는 많으므로, 사이트를 아무거나 선택하자
상위 상단 좌측의 View를 Category로 변경 후
Devel에서 필요한 것들이 있다면 설치 Cross Compiler (Cygwin or Mingw64)
Net->openssh 및 ssh library 설치 ( 소스는 제외)
설치된 Package를 실행
2.1 Cygwin 제거방법
위에서 설명했듯이 Cygwin은 제어판의 프로그램에 나오지 않아서 직접삭제를 해야한다.
그리고, Cygwin에서 사용하고 있는 파일과 데몬이 있다고 중지를 하고 삭제를 진행을 해야한다.
regedit를 이용하여 레지스트리를 편집을 하고, 가능하면 편집의 찾기를 이용하여 찾자
Cygwin or Cygnus Solutions
아래의 Cygnus Solutions에서 Cygwin으로 삭제
http://infoarts.tistory.com/25
3. Cygwin 명령어와 Window 공유 (Eclipse 와 공유)
https://www.howtogeek.com/howto/41382/how-to-use-linux-commands-in-windows-with-cygwin/
4. Cygwin 설치 후 SSH Client 설정 (중요)
외부에 Linux or Unix SSH Server가 존재하며 이는 Build Server 로 동작할 것이다.
Window에서는 상위에서 Cygwin을 이용하여 Openssh가 설치된 상태이며, Cygwin Terminal or CMD 명령으로 ssh를 실행이 가능하도록 설정한다.
Window에서 SSH Server에 매번 Password 입력없이 동작하게 하려고 목적이다.
http://marobiana.tistory.com/53
https://m.blog.naver.com/PostView.nhn?blogId=ccm&logNo=60185667224&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F
http://www.skybert.net/windows/creating-an-ssh-key-on-windows/
Cygwin에 크로스 컴파일러로 Cygwin와 MinGW 존재하며, 이를 설치를 하여 이곳에 설치를 해도 무방하다
윈도우에서 다양한 Linux Tool Package를 사용이 가능하며, 크로스 컴파일러로도 사용하기때문에 이를 설치한다.
현재 나의 경우는 ssh를 이용하여 이클립스와 연동하여 사용하는 것이 주 목적이다.
- Download (Cygwin)설치
상위 Cygwin에 MingGW도 포함
- MingGW 참고
http://rinovation.tistory.com/2
https://www.eclipse.org/forums/index.php/t/1073505/
2. Cygwin 설치 및 재설치
Cygwin은 윈도우의 제어판에서 프로그램 제거를 할 수가 없다.
설치시 이부분을 정확하게 인지하고 있어야한다.
setup-x86_64.exe 을 다시 실행하여 필요한 Package를 추가하여 재설치가 가능하다
- Cygwin 설치방법 및 재설치
상위 그림에서 패키지를 제공해주는 사이트는 많으므로, 사이트를 아무거나 선택하자
상위 상단 좌측의 View를 Category로 변경 후
Devel에서 필요한 것들이 있다면 설치 Cross Compiler (Cygwin or Mingw64)
Net->openssh 및 ssh library 설치 ( 소스는 제외)
- Cygwin 설치후 SSH 동작확인
설치된 Package를 실행
2.1 Cygwin 제거방법
위에서 설명했듯이 Cygwin은 제어판의 프로그램에 나오지 않아서 직접삭제를 해야한다.
그리고, Cygwin에서 사용하고 있는 파일과 데몬이 있다고 중지를 하고 삭제를 진행을 해야한다.
regedit를 이용하여 레지스트리를 편집을 하고, 가능하면 편집의 찾기를 이용하여 찾자
Cygwin or Cygnus Solutions
아래의 Cygnus Solutions에서 Cygwin으로 삭제
- HKEY_LOCAL_MACHINE\SOFTWARE\Cygwin
- HKEY_CURRENT_USER\Software\Cygwin
- HKEY_USERS\.Default\Software\Cygwin (현재 없음)
http://infoarts.tistory.com/25
3. Cygwin 명령어와 Window 공유 (Eclipse 와 공유)
- Window Key + Pause/Break
- 고급시스템 설정 선택 (좌측메뉴)
- 시스템속성창 의 고급->환경변수 선택 (맨아래에 위치)
- 환경변수창이 아래의 시스템변수 PATH 선택
- PATH 에 ;C:\cygwin64\bin 추가
https://www.howtogeek.com/howto/41382/how-to-use-linux-commands-in-windows-with-cygwin/
4. Cygwin 설치 후 SSH Client 설정 (중요)
외부에 Linux or Unix SSH Server가 존재하며 이는 Build Server 로 동작할 것이다.
Window에서는 상위에서 Cygwin을 이용하여 Openssh가 설치된 상태이며, Cygwin Terminal or CMD 명령으로 ssh를 실행이 가능하도록 설정한다.
Window에서 SSH Server에 매번 Password 입력없이 동작하게 하려고 목적이다.
- SSH의 Key 생성
$ ssh-keygen -t rsa // 함께 엔터 id_rsa 생성 $ ls .ssh // id_rsa 생성확인
- Target Server 에 생성된 Key 복사
$ ssh-copy-id jhlee@192.168.1.100 // SSH Server (ID: jhlee )
- ID입력만으로 Password 없이 로그인 가능
$ ssh jhlee@192.168.1.100 // 이제 암호 없이 SSH Server 접속가능 $ ls .ssh id_rsa id_rsa.pub known_hosts
http://marobiana.tistory.com/53
https://m.blog.naver.com/PostView.nhn?blogId=ccm&logNo=60185667224&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F
http://www.skybert.net/windows/creating-an-ssh-key-on-windows/
2/19/2016
Eclipse Neon CDT (C/C++) 기본사용 및 원격 빌드
1. Project 생성 전 확인사항
Project 생성은 기존 소스가 존재하여도 이를 Project를 생성하여 각 기존소스 or New Source를 위해 관련 설정 및
소스분석을 위한 Index를 생성을 한다.
현재 Linux Build Server와 같이 구성할 것이므로, 아래의 참조내용을 이해하고 사용하자.
상위구성이 되었다면, Build Server와 Window와 연결 Interface를 Network Driver를 만들어주어 쉽게 접근하도록 하자.
https://help.eclipse.org/luna/index.jsp?topic=%2Forg.eclipse.ptp.rdt.doc.user%2Fhtml%2Fgettingstarted%2Fcreating_a_remote_project.html
1.1 Project 기본생성 및 제거
생성과 동시에 우측 하단에 Refreshing Working Space라고 하며 진행이 되며 보통 Index도 함께 생성이 된다.
2. Eclipse의 설정
Eclipse의 설정들은 아래와 같이 구성이 되며, Project Properties의 경우는 세부 설정이며 Project 마다 변경이 될 수 있다.
하지만 Window->Preference의 경우는 전체 설정이라고 생각하면 될 것이다.
2.1 Project의 Properties
이제 생성된 Project의 세부설정을 변경하고 싶다면 아래와 같이 둘 중 하나만 하면된다.
Window의 Eclipse에서 SSH를 통하여 Linux Build Server에서 Source를 Build를 하기위해서 다음과 같은 설정필요
3.1 Make Target 생성
SSH 원격빌드를 하기 위해서 Make Target를 생성한다.
Window->Show View->Other 에서 Make Target 선택
or
아래 그림과 같이 Project Explorer 에서 Make Target 선택->Create or Build
상위에서 Make Target->Create or Build 선택
Make Targets->Add or Edit 선택 후 Modify Make Target 창 설정
Build Setting : 현재 Stop on first build error만 설정했지만 (원격이므로 설정의미가 없음)
Make Target을 이용하여 Eclipse에서 Console로 쉽게 빌드 확인 (SSH 원격빌드)
에러시 한글문제 깨지는 문제발생 (UTF8로 설정하는 방법없음)
https://m.blog.naver.com/PostView.nhn?blogId=ccm&logNo=60185667224&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F
https://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.cdt.doc.user%2Ftasks%2Fcdt_t_cbuild_pref.htm
3.2 Build Server의 설정 및 Shell Script
Window에서 SSH Server로 접속하여 Build를 한번에 해야 하기 때문에 기존에 있는 Makefile or Shell script를 이용하여 쉽게 동작하도록 작성하자.
아래의 예는 간단히 설정파일과 Makefile관련부분을 정리
4. Eciplse Neon의 편이성 설정
아래기능을 이용하여 창 분할 기능 및 Remote System 및 편의기능 설정
이것을 사용하는 목적은 순전히 ctags 기능때문이지만 이용할수 없다고 하니 별다른 도움이 되지 않을 것 같다.
http://zoningout.tistory.com/entry/eclipse%EC%97%90%EC%84%9C-vi-mode%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-1
4.1 Remote System 이용
Eclipse에서 Build Server의 부분을 이용하는 것을 말하며 Remote System에서는 기본적으로 SSH Client가 제공이 된다.
위의 3가지 기능을 사용하면, Virtualbox의 Server와 편하게 SSH를 접속할 수 있을 뿐만 아니라,
SFTP를 이용하여 윈도우의 탐색기 기능처럼 사용이 가능하지만 기능이 제한적이다.
그래서, 가급적이면 SFTP하려고 한다.
참으로 좋은 개발 Tool이며 편한 것 같다.
현재 XShell을 사용을 하고 있지만, Eclipse도 꽤 괜찮은 것 같다고 생각이 들지만, XShell 보다 좀 불편해서 그냥 Xshell을 별도 사용중이다.
XShell 역시 위 두 기능을 제공하고 있다. (SSH 와 SFTP 기능 )
vi 편집기를 이용하는데, ssh를 이용하여 편하게 eclipse에서 편집이 가능하다.
다만 설정을 UTF-8로 변경을 해줘야 한다.
출처:
http://forum.falinux.com/zbxe/index.php?document_srl=791415&mid=lecture_tip
Project 생성은 기존 소스가 존재하여도 이를 Project를 생성하여 각 기존소스 or New Source를 위해 관련 설정 및
소스분석을 위한 Index를 생성을 한다.
현재 Linux Build Server와 같이 구성할 것이므로, 아래의 참조내용을 이해하고 사용하자.
- 빌드서버와 Eclipse 기본환경구성이해
- Eclipse CDT 설치 및 확장
- Window에 Linux Tool 설치
상위구성이 되었다면, Build Server와 Window와 연결 Interface를 Network Driver를 만들어주어 쉽게 접근하도록 하자.
https://help.eclipse.org/luna/index.jsp?topic=%2Forg.eclipse.ptp.rdt.doc.user%2Fhtml%2Fgettingstarted%2Fcreating_a_remote_project.html
- Project Explorer 창설정
- Window->Show View->Other 선택
- General->Project Explorer 설정
1.1 Project 기본생성 및 제거
- 프로젝트 생성 및 C/C++ Indexer 생성
기존 Linux Code를 찾아 이곳에 등록을 하고 Project를 새로 생성을 하자
- File->New->Project
- Makefile Project with Existing Code 선택
- None or Cross GCC 선택
생성과 동시에 우측 하단에 Refreshing Working Space라고 하며 진행이 되며 보통 Index도 함께 생성이 된다.
- 프로젝트 제거
2. Eclipse의 설정
Eclipse의 설정들은 아래와 같이 구성이 되며, Project Properties의 경우는 세부 설정이며 Project 마다 변경이 될 수 있다.
하지만 Window->Preference의 경우는 전체 설정이라고 생각하면 될 것이다.
- Window->Preferences
- Project의 Properties
2.1 Project의 Properties
이제 생성된 Project의 세부설정을 변경하고 싶다면 아래와 같이 둘 중 하나만 하면된다.
- Project->Properties 선택
- Project Explorer 창에서 Project 선택 후 우측 클릭 Properties 선택
만약 활성화가 되지 않았다면, 왼쪽 Project Explorer에서 Project를 선택을 하면 활성화가 된다.
UTF-8 / MS949
MS949가 없다면 Window->Preferences의 General 의 Workspace 부분을 한번살펴보자
다른부분은 한번 살펴보자
3. 원격 Build 설정 (Project Target) 설정- Resource 확인사항
UTF-8 / MS949
MS949가 없다면 Window->Preferences의 General 의 Workspace 부분을 한번살펴보자
다른부분은 한번 살펴보자
Window의 Eclipse에서 SSH를 통하여 Linux Build Server에서 Source를 Build를 하기위해서 다음과 같은 설정필요
- cygwin의 openssh 설치필요
- cygwin의 ssh 설정 필요 ( SSH 암호 없이 로그인이 가능하도록 설정)
- Window에 Linux Tool (Cygwin의 SSH기능 설치)
3.1 Make Target 생성
SSH 원격빌드를 하기 위해서 Make Target를 생성한다.
Window->Show View->Other 에서 Make Target 선택
or
아래 그림과 같이 Project Explorer 에서 Make Target 선택->Create or Build
상위에서 Make Target->Create or Build 선택
Make Targets->Add or Edit 선택 후 Modify Make Target 창 설정
- Modify Make Target 창 설정 (상위 좌측의 그림설정)
- Target Name: 이클립스에서 보기위한 Target Name (e.g uboot)
- Make Target: 실제 Makefile의 Target Name (Window의 Makefile을 아니므로, 사용안함)
- Build Command: SSH를 이용하여 원격빌드를 설정 (아래 참조)
ssh jhlee@192.168.1.100 'source ~/am335x/setAM335x; make -C ~/am335x/ti-processor-sdk-linux-am335x-evm-03.00.00.04 u-boot'
Build Setting : 현재 Stop on first build error만 설정했지만 (원격이므로 설정의미가 없음)
- Make Target 창 -> Build (원격빌드)
Make Target을 이용하여 Eclipse에서 Console로 쉽게 빌드 확인 (SSH 원격빌드)
에러시 한글문제 깨지는 문제발생 (UTF8로 설정하는 방법없음)
https://m.blog.naver.com/PostView.nhn?blogId=ccm&logNo=60185667224&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F
- Eclipse Console 관련설정
https://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.cdt.doc.user%2Ftasks%2Fcdt_t_cbuild_pref.htm
3.2 Build Server의 설정 및 Shell Script
Window에서 SSH Server로 접속하여 Build를 한번에 해야 하기 때문에 기존에 있는 Makefile or Shell script를 이용하여 쉽게 동작하도록 작성하자.
아래의 예는 간단히 설정파일과 Makefile관련부분을 정리
$ cat ~/am335x/setAM335x export ARCH=armv7-a export TI_SDK_PATH=/home/jhlee/am335x/ti-processor-sdk-linux-am335x-evm-03.00.00.05 export LINUX_DEVKIT_PATH=${TI_SDK_PATH}/linux-devkit export CROSS_COMPILE=${LINUX_DEVKIT_PATH}/sysroots/x86_64-arago-linux/usr/bin/arm-linux-gnueabihf- $ cd ~/am335x/ti-processor-sdk-linux-am335x-evm-03.00.00.04 $ vi Makefile linux: linux-dtbs @echo ================================= @echo Building the Linux Kernel @echo ================================= $(MAKE) -C $(LINUXKERNEL_INSTALL_DIR) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) $(DEFCONFIG) $(MAKE) -j $(MAKE_JOBS) -C $(LINUXKERNEL_INSTALL_DIR) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) zImage $(MAKE) -j $(MAKE_JOBS) -C $(LINUXKERNEL_INSTALL_DIR) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) modules ...... u-boot: linux-dtbs @echo =================================== @echo Building U-boot @echo =================================== $(MAKE) -j $(MAKE_JOBS) -C $(TI_SDK_PATH)/board-support/u-boot-* CROSS_COMPILE=$(CROSS_COMPILE) $(UBOOT_MACHINE) $(MAKE) -j $(MAKE_JOBS) -C $(TI_SDK_PATH)/board-support/u-boot-* CROSS_COMPILE=$(CROSS_COMPILE) DTC=$(LINUXKERNEL_INSTALL_DIR)/scripts/dtc/dtc
4. Eciplse Neon의 편이성 설정
아래기능을 이용하여 창 분할 기능 및 Remote System 및 편의기능 설정
- Window->Editor->Toggle Split Editor ( 화면분할)
- Window->Show View->Remote System
- Window->Preference ( 기타 모든 설정)
- VI관련 기능
이것을 사용하는 목적은 순전히 ctags 기능때문이지만 이용할수 없다고 하니 별다른 도움이 되지 않을 것 같다.
- Help->Install New Software
- http://vrapper.sourceforge.net/update-site/stable/
http://zoningout.tistory.com/entry/eclipse%EC%97%90%EC%84%9C-vi-mode%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-1
4.1 Remote System 이용
Eclipse에서 Build Server의 부분을 이용하는 것을 말하며 Remote System에서는 기본적으로 SSH Client가 제공이 된다.
- SSH Client 기능
- SFTP Client 기능 (윈도우 탐색기 처럼 사용가능하나 불편함 )
- Local Files->Drivers 이용 (Samba로 Window에서 Network Driver로 연결)
위의 3가지 기능을 사용하면, Virtualbox의 Server와 편하게 SSH를 접속할 수 있을 뿐만 아니라,
SFTP를 이용하여 윈도우의 탐색기 기능처럼 사용이 가능하지만 기능이 제한적이다.
그래서, 가급적이면 SFTP하려고 한다.
참으로 좋은 개발 Tool이며 편한 것 같다.
현재 XShell을 사용을 하고 있지만, Eclipse도 꽤 괜찮은 것 같다고 생각이 들지만, XShell 보다 좀 불편해서 그냥 Xshell을 별도 사용중이다.
XShell 역시 위 두 기능을 제공하고 있다. (SSH 와 SFTP 기능 )
- Remote System 설정방법
- Window->Perspective->Open Perspective-> Others -> Remote Systems Explorer 선택
- 생성된 Remote System의 좌측의 맨위 아이콘 (Define a connection to remote system) or 마우스 우측 클릭 후, new->connection를 선택
- SSH Only 선택 후 본인의 SSH Server 관련 설정
- Remote System에서 new->connection 선택 ( 상위 1번동일 )
- SSH Only 설정 및 관련 설정 (상위 2번 동일)
- SSH를 설정하면, 자동으로 SFTP도 설정이 됨 (상위 3번 동일)
vi 편집기를 이용하는데, ssh를 이용하여 편하게 eclipse에서 편집이 가능하다.
다만 설정을 UTF-8로 변경을 해줘야 한다.
- SSH에서 한글깨짐문제
- Window>Preferences 선택
- General>Workspace 선택
- 아래메뉴의 OTHER를 선택하고 UTF-8과 UNIX 설정
http://forum.falinux.com/zbxe/index.php?document_srl=791415&mid=lecture_tip
2/17/2016
Kernel 과 Uboot Booting 문제
매번 느끼지는 것지만, 처음 Uboot와 Kernel이 Booting이 안되는 첫번째 에러는
MACHINE_TYPE에러인것 같다.
다양한 설정 방법이 존재한다.
MACHINE_TYPE에러인것 같다.
$ vi .config # # DaVinci Board Type # # CONFIG_MACH_DAVINCI_DM365_EVM is not set # CONFIG_MACH_DAVINCI_DM365_IPNC is not set CONFIG_MACH_DAVINCI_DM368_IPNC=y $ vi ./include/generated/mach-types.h #ifdef CONFIG_MACH_DAVINCI_DM368_IPNC # ifdef machine_arch_type # undef machine_arch_type # define machine_arch_type __machine_arch_type # else # define machine_arch_type MACH_TYPE_DAVINCI_DM368_IPNC # endif # define machine_is_davinci_dm368_ipnc() (machine_arch_type == MACH_TYPE_DAVINCI_DM368_IPNC) #else # define machine_is_davinci_dm368_ipnc() (0) #endif $ vi ./arch/arm/mach-davinci/board-dm368-ipnc.c MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM36x IPNC") .boot_params = (0x80000100), .map_io = dm365_evm_map_io, .init_irq = davinci_irq_init, .timer = &davinci_timer, .init_machine = dm368_evm_init, MACHINE_END
- Kernel 설정
다양한 설정 방법이 존재한다.
make menuconfig // 일반 설정 make xconfig (gconf tool 사용) , QT (KDE) based GUI Kernel config make gconfig (gkc tools ) GTK , GNOMEhttps://www.halolinux.us/fedora-7-reference/kernel-configuration-tools.html
2/16/2016
Audio-ALSA SOC Framework-Codec Driver ( Kernel)
1. Hardware 기본구성 및 설정
위 구성을 보면 AIC3x CODEC은 BCLK과 WCLK(Frame sync)를 제공하며, Data는 이 Frame Sync의 Timing에 맞추어 전송하고 받는다.
기본적인 통신은 Synchronous이며 설정에 따라 Interface의 방식은 변경되어 진다..
http://processors.wiki.ti.com/index.php/Sitara_Linux_Audio_Hardware_Overview
아래의 설정은 ALSA에서 설정하는 SOC 설정모드이며, Codec 입장에서 기술된다.
CODEC는 위와 같이 CLOCK과 Frame Sync(WCLK)을 제공을 한다.
그러므로, CODEC이 BCLK Master Frame Sync Master이므로, SND_SOC_DAIFMT_CBM_CFM 이다.
가장 일반적인게 I2S이며, DSP Mode A/B 혹은 AC97인데, Codec Chip이 지원되는 거에 따라 변경해서 사용하자.
Offset은 McBSP의 Data Delay에 같이 설정해야하며
Offset을 주느냐에 따라 DSP_B모드가 되며,NB_NF의 선택 BCLK과 WCLK의 극성선택이다.
2. I2C driver 기본확인사항
HW Codec의 I2C Driver는 거의 동일하며, 실제적인 Codec의 관련설정을 하는 것이므로, 사용시 반드시 Codec Datasheet와 함께 봐야한다.
2.1 Audio Codec 등록 확인
아래와 같이 기본 board에서 등록이 되어있는지 확인하고, Kernel config에서지원되는 것을 확인을 하자.
만약 지원이 되지 않는다면, 이제 Audio Codec Driver를 가져와서, 이를 Porting하자 .
아래와 같이 등록을 해야, 실제 Audio Codec Driver에서 발견가능하다.
보통 Codec Driver 들은 여러종류의 칩의 지원을 하므로, 아래와 같이 board에서 이름을 정확히 정해줘야한다.
현재 DM368에, AIC3100을 올려서 수정하고 있다.
A. DM368
B. DM355
아래와 같이, plaform_data에 argument를 넣어 전달이 가능하다.
그러면, i2c_probe할 때, struct i2c_client *i2c 에서 i2c->dev.platform_data 전달 받을 수 있다.
2.2 Audio Codec Driver 기본동작
AIC3x Driver 즉 HW Codec Driver 예제이며 구조는 다음과 같다.
3. Codec Porting 시 체크사항
- TI McASP 와 AIC3x HW Codec 의 연결사항
- BCLK (BIT CLOCK) : Codec Clock 제공 (Master)
- WCLK (WORD CLOCK) : Codec Frame Sync 제공 (Master)
- RX Data : RX Data (Encoding Data)
- TX Data : TX Data (Decoding Data )
위 구성을 보면 AIC3x CODEC은 BCLK과 WCLK(Frame sync)를 제공하며, Data는 이 Frame Sync의 Timing에 맞추어 전송하고 받는다.
기본적인 통신은 Synchronous이며 설정에 따라 Interface의 방식은 변경되어 진다..
http://processors.wiki.ti.com/index.php/Sitara_Linux_Audio_Hardware_Overview
1.1 ALSA SOC-DAIFMT 설정
아래의 설정은 ALSA에서 설정하는 SOC 설정모드이며, Codec 입장에서 기술된다.
- CBM: Codec Clock Master: Codec Chip Clock 제공
- CFM: Codec Frame Sync Master: Codec Chip Frame Sync 제공
CODEC는 위와 같이 CLOCK과 Frame Sync(WCLK)을 제공을 한다.
그러므로, CODEC이 BCLK Master Frame Sync Master이므로, SND_SOC_DAIFMT_CBM_CFM 이다.
- 둘 사이의 Master/Slave 관련결정
$ vi include/sound/soc-dai.h #define SND_SOC_DAIFMT_CBM_CFM (0 << 12) /* codec clk & FRM master */ #define SND_SOC_DAIFMT_CBS_CFM (1 << 12) /* codec clk slave & FRM master */ #define SND_SOC_DAIFMT_CBM_CFS (2 << 12) /* codec clk master & frame slave */ #define SND_SOC_DAIFMT_CBS_CFS (3 << 12) /* codec clk & FRM slave */
- 둘 사이의 실제적인 Interface 결정 과 Clock
$ vi include/sound/soc-dai.h #define SND_SOC_DAIFMT_I2S 0 /* I2S mode */ #define SND_SOC_DAIFMT_RIGHT_J 1 /* Right Justified mode */ #define SND_SOC_DAIFMT_LEFT_J 2 /* Left Justified mode */ #define SND_SOC_DAIFMT_DSP_A 3 /* L data MSB after FRM LRC */ #define SND_SOC_DAIFMT_DSP_B 4 /* L data MSB during FRM LRC */ #define SND_SOC_DAIFMT_AC97 5 /* AC97 */ #define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bit clock + frame */ #define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal BCLK + inv FRM */ #define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert BCLK + nor FRM */ #define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert BCLK + FRM */
- DM368의 최종결정
$ vi ./sound/soc/davinci/davinci-evm.c // 현재 DM368 설정
#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
- AIC3100 의 지원되는 I2S와 DSP Mode
Offset은 McBSP의 Data Delay에 같이 설정해야하며
Offset을 주느냐에 따라 DSP_B모드가 되며,NB_NF의 선택 BCLK과 WCLK의 극성선택이다.
2. I2C driver 기본확인사항
HW Codec의 I2C Driver는 거의 동일하며, 실제적인 Codec의 관련설정을 하는 것이므로, 사용시 반드시 Codec Datasheet와 함께 봐야한다.
2.1 Audio Codec 등록 확인
아래와 같이 기본 board에서 등록이 되어있는지 확인하고, Kernel config에서지원되는 것을 확인을 하자.
만약 지원이 되지 않는다면, 이제 Audio Codec Driver를 가져와서, 이를 Porting하자 .
아래와 같이 등록을 해야, 실제 Audio Codec Driver에서 발견가능하다.
보통 Codec Driver 들은 여러종류의 칩의 지원을 하므로, 아래와 같이 board에서 이름을 정확히 정해줘야한다.
현재 DM368에, AIC3100을 올려서 수정하고 있다.
A. DM368
$ vi arch/arm/mach-davinci/board-dm368-ipnc.c
static struct i2c_board_info i2c_info[] = {
{
I2C_BOARD_INFO("tlv320aic3x", 0x18), // AIC3100의 7bit Address는 0x18 설정
},
};
static void __init evm_init_i2c(void)
{
davinci_init_i2c(&i2c_pdata);
i2c_register_board_info(1, i2c_info, ARRAY_SIZE(i2c_info));
}
B. DM355
아래와 같이, plaform_data에 argument를 넣어 전달이 가능하다.
그러면, i2c_probe할 때, struct i2c_client *i2c 에서 i2c->dev.platform_data 전달 받을 수 있다.
$ vi arch/arm/mach-davinci/board-dm355-evm.c static struct i2c_board_info dm355evm_i2c_info[] = { { I2C_BOARD_INFO("dm355evm_msp", 0x25), .platform_data = dm355evm_mmcsd_gpios, }, /* { plus irq }, */ { I2C_BOARD_INFO("tlv320aic33", 0x1b), }, }; static void __init evm_init_i2c(void) { davinci_init_i2c(&i2c_pdata); gpio_request(5, "dm355evm_msp"); gpio_direction_input(5); dm355evm_i2c_info[0].irq = gpio_to_irq(5); i2c_register_board_info(1, dm355evm_i2c_info, ARRAY_SIZE(dm355evm_i2c_info)); }
2.2 Audio Codec Driver 기본동작
AIC3x Driver 즉 HW Codec Driver 예제이며 구조는 다음과 같다.
- module init 이 호출되면서, i2c_add_driver 호출하여, i2c driver 를 등록
- 이미 등록된 I2C device가 있으면, 이를 찾아 probe를 호출 (platform_driver 구조와 동일)
- aic3x_i2c_probe 는 snd_soc_register_codec 사용하여 Codec Driver를 등록한다.
- aic3x_dai를 snd_soc_dai를 등록하여 이는 codec_dai 와 cpu_dai와 mapping 동작함
$ vi sound/soc/codecs/tlv320aic3x.c static const struct i2c_device_id aic3x_i2c_id[] = { [AIC3X_MODEL_3X] = { "tlv320aic3x", 0 }, [AIC3X_MODEL_33] = { "tlv320aic33", 0 }, [AIC3X_MODEL_3007] = { "tlv320aic3007", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); /* machine i2c codec control layer */ static struct i2c_driver aic3x_i2c_driver = { .driver = { .name = "tlv320aic3x-codec", .owner = THIS_MODULE, }, .probe = aic3x_i2c_probe, // 이미 i2c_register_board_info 했을 경우, probe를 실행 .remove = aic3x_i2c_remove, .id_table = aic3x_i2c_id, }; static inline void aic3x_i2c_init(void) { int ret; ret = i2c_add_driver(&aic3x_i2c_driver); if (ret) printk(KERN_ERR "%s: error regsitering i2c driver, %d\n", __func__, ret); } static inline void aic3x_i2c_exit(void) { i2c_del_driver(&aic3x_i2c_driver); } static struct snd_soc_codec_driver soc_codec_dev_aic3x = { .set_bias_level = aic3x_set_bias_level, // Reset , 초기화 Codec의 상태별로 설정 .reg_cache_size = ARRAY_SIZE(aic3x_reg), // Cache Size .reg_word_size = sizeof(u8), .reg_cache_default = aic3x_reg, // Codec Default Setting. .probe = aic3x_probe, // aic3x_probe** .remove = aic3x_remove, .suspend = aic3x_suspend, .resume = aic3x_resume, }; #define AIC3X_RATES SNDRV_PCM_RATE_8000_96000 #define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) static struct snd_soc_dai_ops aic3x_dai_ops = { .hw_params = aic3x_hw_params, // CODEC 관련 설정 .digital_mute = aic3x_mute, // .set_sysclk = aic3x_set_dai_sysclk, // CLOCK 관련 설정 .set_fmt = aic3x_set_dai_fmt, // Interface 설정 (format 설정) }; static struct snd_soc_dai_driver aic3x_dai = { .name = "tlv320aic3x-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, .channels_max = 2, .rates = AIC3X_RATES, .formats = AIC3X_FORMATS,}, .capture = { .stream_name = "Capture", .channels_min = 1, .channels_max = 2, .rates = AIC3X_RATES, .formats = AIC3X_FORMATS,}, .ops = &aic3x_dai_ops, }; static int aic3x_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) // Codec Driver 등록 { ....... ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_aic3x, &aic3x_dai, 1); //snd_soc_dai_driver 등록 이는 추후 SOC와 Mappping ...... }
3. Codec Porting 시 체크사항
현재 AIC3100을 사용해야하는데, AIC3x와 정확히 호환되지 않는다.
그리고, AIC3100 Driver (AM3xxx 계열지원) 지원이 되지만 DM368 Kernel ALSA Version과 다르다.
커널 간에 ALSA의 아래사항을 확인해보자.
3.1 ALSA Framework 확인
Kernel의 ALSA 기본 Framework 부분을 확인하자.
A. ALSA 기본 header 체크사항
include/sound/soc.h
include/sound/soc-dapm.h
B. Codec 에 의존된 header 체크
현재 TI TLV Series 사용하므로, 아래의 header를 체크하자. (AIC3100 사용)
만약 Wolfson사의 WM Series를 사용한다면, 다른 header를 체크하자.
include/sound/tlv.h
3.2 I2C Mapping 확인
Code driver 는 요즘 거의 Cache에 Mapping 시켜서 사용하는 것 같다.
기본적으로 사용하고 싶은 register size 만큼 cache에 등록하고,
별도의 kernel/drivers/base/regmap/regmap-i2c.ko 필요한 것 같은데, 불행히도 DM368은 지원하지 않는다.
그래서 그냥 아래와 같이 직접 I2C에 연결해서 사용했다.
Kernel config에 포함이 되어있지 않다면, 아래와 같이 직접 연결하여 사용해야한다.
3.3 CODEC 과 CPU 의 Interface 설정
TI Audio Driver는 현재 아래와 같은 구조로 동작하며, 다른 Driver 일 경우 변경 될 수 있다.
모든 것이 hw_param 의해 설정이 되며, 아래와 같이 개별적으로 Driver 마다 존재한다.
ALSA에서 hw_param가 호출이 되면, EVM 및 개별 machine, codec, cpu, platform driver의 hw_param이 호출이 된다.
ALSA는 간단하지만 내부 Driver구조들은 제법 많이 복잡하다 관련내용은 추후 다시 설명
그리고, AIC3100 Driver (AM3xxx 계열지원) 지원이 되지만 DM368 Kernel ALSA Version과 다르다.
커널 간에 ALSA의 아래사항을 확인해보자.
3.1 ALSA Framework 확인
Kernel의 ALSA 기본 Framework 부분을 확인하자.
A. ALSA 기본 header 체크사항
include/sound/soc.h
include/sound/soc-dapm.h
B. Codec 에 의존된 header 체크
현재 TI TLV Series 사용하므로, 아래의 header를 체크하자. (AIC3100 사용)
만약 Wolfson사의 WM Series를 사용한다면, 다른 header를 체크하자.
include/sound/tlv.h
3.2 I2C Mapping 확인
Code driver 는 요즘 거의 Cache에 Mapping 시켜서 사용하는 것 같다.
기본적으로 사용하고 싶은 register size 만큼 cache에 등록하고,
별도의 kernel/drivers/base/regmap/regmap-i2c.ko 필요한 것 같은데, 불행히도 DM368은 지원하지 않는다.
그래서 그냥 아래와 같이 직접 I2C에 연결해서 사용했다.
Kernel config에 포함이 되어있지 않다면, 아래와 같이 직접 연결하여 사용해야한다.
static int aic3100_read(struct snd_soc_codec *codec, unsigned int reg) { struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); int ret=0; reg = (reg & 0xff); ret = i2c_smbus_read_byte_data(aic3x->control_data, reg); if (ret < 0) printk("%s error addr=%x \n",__func__,reg); return ret; } static int aic3100_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); int ret=0; reg = (reg & 0xff); value = (value & 0xff); ret = i2c_smbus_write_byte_data(aic3x->control_data, reg, value); if (ret < 0) printk("%s error addr=%x val=%x \n",__func__,reg,value); return ret; }
3.3 CODEC 과 CPU 의 Interface 설정
TI Audio Driver는 현재 아래와 같은 구조로 동작하며, 다른 Driver 일 경우 변경 될 수 있다.
모든 것이 hw_param 의해 설정이 되며, 아래와 같이 개별적으로 Driver 마다 존재한다.
ALSA에서 hw_param가 호출이 되면, EVM 및 개별 machine, codec, cpu, platform driver의 hw_param이 호출이 된다.
ALSA는 간단하지만 내부 Driver구조들은 제법 많이 복잡하다 관련내용은 추후 다시 설명
- evm_hw_param 인 경우
$ vi ./sound/soc/soc-core.c soc_pcm_hw_params // 개별가 존재하면, hw_params 호출 machine ,codec, cpu, plaftform, $ vi ./sound/soc/davinci/davinci-evm.c #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) static int evm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { ..... /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT); // CODEC Driver 에 set_fmt 함수 호출, if (ret < 0) return ret; /* set cpu DAI configuration */ ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); // McBSP Driver 에 format 적용 if (ret < 0) return ret; /* set the codec system clock */ ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT); // Codec Driver 의 set_sysclk 호출 if (ret < 0) return ret; ... }
2/15/2016
Audio-ALSA Framework
1. ALSA의 기본구조
ALSA(Advanced Linux Sound Architecture)로 요즘 거의 AP/SoC들은 ALSA의 기반에 맞추어 각 Driver들을 만들어 이곳에 등록하여 동작하도록 구성한다.
ALSA(Advanced Linux Sound Architecture)로 요즘 거의 AP/SoC들은 ALSA의 기반에 맞추어 각 Driver들을 만들어 이곳에 등록하여 동작하도록 구성한다.
그래서 ALSA Format? 이 존재하고 각 AP/SoC 업체들은 각 자신들의 BSP Driver를 이 Format에 맞추어 동작가능하도록 하고 호환성을 높인다.
1.1 OSS와 ALSA
OSS (Open Sound System) 약어로 Linux 2.4에서 공식적으로 사용을 했다고 한다.이때도 Audio Driver 수정했지만, 모르고 수정했다.
사실 Audio 관련 Driver는 Kernel 2.4 때 주로 많이 직접 Audio Driver를 만들었지만, 그때는 OSS라는 이름을 잘 못들은 것 같다.
OSS 관련내용
https://en.wikipedia.org/wiki/Open_Sound_System
http://www.opensound.com/pguide/oss.pdf
1.2 TI 사의 ALSA 전체구조
ALSA의 기본 전체구조는 아래와 같으며, 다른 SOC 플랫폼도 유사하다.
아래 구조는 TI사의 Sitara의 구조에서 가져왔다.
자세한 내용은 아래의 페이지 참조
TI사의 ALSA 전체구조
http://alsa.opensrc.org/Alsa-utils
ftp://ftp.alsa-project.org/pub/utils/
1.1 OSS와 ALSA
ALSA(Advanced Linux Sound Architecture)로 Linux에서만 사용이 되며, Kernel version 2.5에서 부터 추가가 되었다고 한다.
ALSA라는 이름 부각되는 것은 Linux Kernel 이 2.4 -> 2.5로 변경되면서 Driver 전체구조자체가 Platform 구조로 변경되었기 때문인 것 같다.
사실 Audio 관련 Driver는 Kernel 2.4 때 주로 많이 직접 Audio Driver를 만들었지만, 그때는 OSS라는 이름을 잘 못들은 것 같다.
Kernel 2.4 Audio Driver 의 경우는 좀 제 각각인데다가, 필요에따라 확장하고 그랬다.
또한 각 Audio Chip Vendor에 따라 구조역시 조금씩 다르다.
OSS 관련내용
https://en.wikipedia.org/wiki/Open_Sound_System
http://www.opensound.com/pguide/oss.pdf
1.2 TI 사의 ALSA 전체구조
ALSA의 기본 전체구조는 아래와 같으며, 다른 SOC 플랫폼도 유사하다.
아래 구조는 TI사의 Sitara의 구조에서 가져왔다.
자세한 내용은 아래의 페이지 참조
TI사의 ALSA 전체구조
https://en.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture
http://processors.wiki.ti.com/index.php/Sitara_Linux_Audio_Driver_Overview
Linux의 Audio Driver의 기본구조는 ALSA Framework이며, 이에 관련된 Project는 다음과 같으며, 위와 같다.
http://processors.wiki.ti.com/index.php/Sitara_Linux_Audio_Driver_Overview
Linux의 Audio Driver의 기본구조는 ALSA Framework이며, 이에 관련된 Project는 다음과 같으며, 위와 같다.
ALSA 관련문서
http://www.alsa-project.org/main/index.php/Documentation
http://www.alsa-project.org/main/index.php/Download
2. ALSA의 전체구조
ALSA의 구조를 간단히 2단계로 나누면 간단하다, KERNEL과 APP이다.
하지만 세부화로 나누게되면, KERNEL도 COMMON한 부분이 있고, 포팅을 해야하는 부분이 있기에 이를 또 나누게 된다.
그리고, 이를 USER에게 기능을 제공을 하면, Alsa User Lib가 이를 가지고 사용을 한다.
2.1 ALSA SOC CORE (KERNEL)
Embeded Linux에서는 해당 Chip마다 각 ALSA Soc Driver를 제공하며,Framework이 SOC마다 약간 상이하며, Version에 따라 다를 수 있다.
http://www.alsa-project.org/main/index.php/Documentation
http://www.alsa-project.org/main/index.php/Download
2. ALSA의 전체구조
ALSA의 구조를 간단히 2단계로 나누면 간단하다, KERNEL과 APP이다.
하지만 세부화로 나누게되면, KERNEL도 COMMON한 부분이 있고, 포팅을 해야하는 부분이 있기에 이를 또 나누게 된다.
그리고, 이를 USER에게 기능을 제공을 하면, Alsa User Lib가 이를 가지고 사용을 한다.
2.1 ALSA SOC CORE (KERNEL)
- Codec Driver : AIC31x, AIC3100 Audio Codec Driver를 말하며, I2C로 Driver이다.
- Platform Driver: TI인 경우 주로 McBSP or McASP Audio Driver이며, DMA기능을 포함한다.
- Machine Driver: Codec과 Platform Driver를 연결시켜주는 Driver이며, Machine에 대한 설정 담당한다.
Embeded Linux에서는 해당 Chip마다 각 ALSA Soc Driver를 제공하며,Framework이 SOC마다 약간 상이하며, Version에 따라 다를 수 있다.
ALSA Library와 직접적으로 통신을 하며, 기능을 제공을 한다.
http://www.alsa-project.org/main/index.php/ASoC
2.2 ALSA Library (USER)
http://www.alsa-project.org/alsa-doc/alsa-lib/
http://www.alsa-project.org/main/index.php/ALSA_Library_API
2.3 ALSA Application (USER)
http://www.alsa-project.org/main/index.php/Applications
Android로 가면, Hal이 될수도 있다.
http://www.alsa-project.org/main/index.php/ASoC
2.2 ALSA Library (USER)
- ALSA PCM 기본설명
http://www.alsa-project.org/alsa-doc/alsa-lib/
http://www.alsa-project.org/main/index.php/ALSA_Library_API
2.3 ALSA Application (USER)
- ALSA를 이용한 다양한 Application Program들
http://www.alsa-project.org/main/index.php/Applications
Android로 가면, Hal이 될수도 있다.
- ALSA Test (alsa-utils)
http://alsa.opensrc.org/Alsa-utils
ftp://ftp.alsa-project.org/pub/utils/
I2C TEST TOOLs
1. Linux 에서 I2C Test Tool
Android 이나, Linux에서 많이 사용되고 있는 Tool이며, SDK에 많이 포함이 되고 있다.
만약 포함이 되어 있지 않다면, 아래에서 download 해서 cross compile하여 넣자.
https://github.com/groeck/i2c-tools
https://elinux.org/Interfacing_with_I2C_Devices
https://github.com/JeonghunLee/i2c-tools
2. CROSS COMPILE
상위 소스의 tools를 보면 관련 binary 소스를 확인이 가능하며, 아래와 같이 빌드하여
간단히 만들고 이 프로그램을 테스트 용도로 사용해보자.
3. 사용법
아래와 같이 네개의 Tool 이 존재하며,
아래와 같이 설정하여 TEST가 가능하며, 자세한 설정은 소스의 Help를 보자
Android 이나, Linux에서 많이 사용되고 있는 Tool이며, SDK에 많이 포함이 되고 있다.
만약 포함이 되어 있지 않다면, 아래에서 download 해서 cross compile하여 넣자.
https://github.com/groeck/i2c-tools
https://elinux.org/Interfacing_with_I2C_Devices
https://github.com/JeonghunLee/i2c-tools
2. CROSS COMPILE
상위 소스의 tools를 보면 관련 binary 소스를 확인이 가능하며, 아래와 같이 빌드하여
간단히 만들고 이 프로그램을 테스트 용도로 사용해보자.
$ vi Makefile prefix = /home/jhlee/dm368/mt5/Source/ipnc_rdk/target/filesys_dm368 ### prefix install 될 장소 CROSS = /home/jhlee/dm368/mt5/Source/dvsdk_ipnctools/linux-devkit/bin/arm-arago-linux-gnueabi- ### CROSS COMPILER $ Make $ Make install // 해당 Filesystem 이동
3. 사용법
아래와 같이 네개의 Tool 이 존재하며,
- i2cdetect
- i2cdump
- i2cset
- i2cget
아래와 같이 설정하여 TEST가 가능하며, 자세한 설정은 소스의 Help를 보자
i2cget ( Linux Device Number) (7bit address) (Device Register)
2/14/2016
GNU Make 사용법 및 다양한 규칙
1. GNU Make의 Manual
개발자라고 하면, Make를 모르는 사람이 없을 것이지만, 직접 Makefile을 처음부터 작성해야하는 일은 요즘 드문일 같다.
하지만, Makefile을 수정해야하는 일과 간혹은 처음부터 만들어야 하는 경우가 존재하며,
그때마다 opensource의 Makefile 파일을 참조하면서 보게 되지만, 매번 Makefile을 작성하기가 힘이 든다. 그래서 아래와 같이 정리하고 한다.
보통 Linux에서는 GNU Make사용하지만 다른 플랫폼에서 사용되는 Make와 완벽하게 호환이 된다고 착각하지 말기 바란다.
기본규칙과 GNU Make 내부 규칙을 가급적 분리해서 알아야 두면 편하다.
Pattern Rule만 소개
https://www.gnu.org/software/make/manual/html_node/Pattern-Rules.html#Pattern-Rules
Old Style Pattern 규칙
https://www.gnu.org/software/make/manual/html_node/Suffix-Rules.html#Suffix-Rules
2.3 Make의 기능의 확장
상위에서도 간단하게 사용했지만, GNU make 내부에 함수가 존재하며, 아래와 같이
이를 이용하면 편한하게 Make 작성이 가능하다.
https://www.gnu.org/software/make/manual/html_node/Functions.html#Functions
https://www.gnu.org/software/make/manual/html_node/Conditionals.html#Conditionals
https://www.gnu.org/software/make/manual/html_node/Conditional-Example.html#Conditional-Example
https://www.gnu.org/software/make/manual/html_node/Conditional-Syntax.html
3. Make의 recipe 구현
make의 recipe는 실제의 동작이며, 가장 중요한 부분이기에 어떻게 사용할 것인지,
응용은 어떻게 할것인지에 대해 좀 자세히 알아보자
3.1 recipe의 Linux command 적용
Linux 내부에서 사용되는 다양한 command를 이용하여, Make 에 적용하는 방법이다.
가장 많이 사용하는 command를 아래와 같이 구성했으며, 이를 보고 간단히 구현을 해보자.
@는 command의 실행을보여주지 않는다.
`` 먼저 이 command를 실행한 후 결과를 연결해준다. (파이프 개념) (stdout -> stdin)
export를 이용하여 변수에 할당 및 변수값 조정을 했었는데, 이부분은 지금 힘든것 같다.
(다른방법으로 찾아보자, 가능하면 user mode에서 해결하자 )
3.2 Make의 recipe 에 script 적용
Shell Script의 기능을 Make 안에 적용하는 것이지만 변수 사용법 이부분은 아래의 변수사용법 참조
이를 이용하면 좀 더 복잡하고 정교한 Make를 만들 것이 가능하다.
이 뿐만 아니라, sed , awk 등 다양한 것을 적용가능하다.
기본 Script를 익혀서 이를 Makefile 내부에 적용을 해보자
그리고 위에서 설명했듯이 Loop의 List 변수의 구분자는 스페이스 이다.
https://www.gnu.org/software/make/manual/html_node/Variables-in-Recipes.html
A. For Loop 예제-1 (recipe 안에서 $$사용)
B. For Loop 예제-2
아래와 같이 1 2 3의 구분자는 스페이스이다.
C. For Loop 예제-3
D. IF문 및 EXIT 예제-1 (File 및 Directory 존재 여부 확인)
http://egaoneko.github.io/os/2015/05/24/linux-starter-guide-8.html#fnref:1
4. GCC의 다양한 Option 설정
이부분은 상위 Implicit-Variables 와 연관이 있으며 Make 내부에 GCC의 옵션 변경을 할때 아래와 같이 GCC Manual을 이용하여 설정을 변경하자
아래의 GCC 옵션들은 GCC-5.4.0 기준이며, 본인이 사용하는 GCC version에 맞추어
문서를 찾아 Index를 찾으면 될 것이다.
https://gcc.gnu.org/onlinedocs/gcc-5.4.0/gcc/Option-Index.html#Option-Index
5. Make의 관련 다양한 예제
Make의 기본 기능은 Target과 그의 종속된 Target 을 연결하여 실행하는 것이다.
그리고, Make를 재귀적용법으로도 실행을 하여 다른 Makefile을 제어도 가능하다.
https://www.joinc.co.kr/w/Site/C/Documents/minzkn_make
http://developinghappiness.com/?p=28
6. GNU Make Manual 관련사항
http://korea.gnu.org/manual/4check/make-3.77/ko/make_toc.html
https://wiki.kldp.org/KoreanDoc/html/GNU-Make/GNU-Make.html#toc8
GNU Make의 Manual 내용이 많다보니, 상위 Manual에서도 아래와 같이 읽어보라고 권하고 있다.
https://www.gnu.org/software/make/manual/html_node/Features.html#Features
https://www.gnu.org/software/make/manual/html_node/Missing.html#Missing
https://www.gnu.org/software/make/manual/html_node/Special-Targets.html#Special-Targets
https://www.gnu.org/software/make/manual/html_node/Quick-Reference.html#Quick-Reference
https://www.gnu.org/software/make/manual/html_node/Options-Summary.html#Options-Summary
7. Kernel Makefile 관련내용
Kernel Makefile을 보면 상위부분은 복잡하지만, 밑으로 갈수록으로 모듈화가 잘되어있어
사용하기가 편하다.
U-Boot Makefile 역시 비슷하지만 다르게 구성이 되어있지만, 유사한 부분이 많이 있다.
솔직히 Kernel Makefile과 U-Boot Makefile은 수정할 일이 거의 없으며 간단한 Config 규칙과 Makefile 추가하는 식을 알면된다.
https://www.kernel.org/doc/Documentation/kbuild/makefiles.txt
개발자라고 하면, Make를 모르는 사람이 없을 것이지만, 직접 Makefile을 처음부터 작성해야하는 일은 요즘 드문일 같다.
하지만, Makefile을 수정해야하는 일과 간혹은 처음부터 만들어야 하는 경우가 존재하며,
그때마다 opensource의 Makefile 파일을 참조하면서 보게 되지만, 매번 Makefile을 작성하기가 힘이 든다. 그래서 아래와 같이 정리하고 한다.
보통 Linux에서는 GNU Make사용하지만 다른 플랫폼에서 사용되는 Make와 완벽하게 호환이 된다고 착각하지 말기 바란다.
기본규칙과 GNU Make 내부 규칙을 가급적 분리해서 알아야 두면 편하다.
2. Make의 기본구성 및 구조
GNU Make or Make의 기본구성은 3가지로 구성 되며, 각 용어와 구성내용을 알아보자.
Makefile 분석을 하면 항상 기본형태는 아래와 같이 구성이 되며, 세부내용들은
천천히 메뉴얼과 함께 봐야할 부분들이다.
https://www.gnu.org/software/make/manual/html_node/Rule-Syntax.html#Rule-Syntax
2.1 Make의 기본구성의 규칙
Make의 Rule은 위에서 언급한 target prerequisites recipe 의 다양한 기능과 구조를 익히면될것 같다.
자세한 내용은 아래의 링크된 Manual을 참조
target 는 wildcard 와 변수도 사용가능하며, 다중 target 등에 다양하게 사용이 가능하다.
target의 특정목적의 target도 존재하니 이부분도 익혀두자.
normal-prerequisites | order-only-prerequisites
1. normal-prerequisites
target 보다 먼저 순서적으로 prerequisites 진행하지만, 종속적인 관계를 유지하고
prerequisites가 target 보다 시간적으로 새거라면 현재 target은 쓸모가 없어지고 동작되지 않는다.
쉽게말해서 빌드 할경우 수정하지 않은 파일을 빌드하지 못하게하는 기능이라고 생각하면된다.
위에서 의 기준은 항상 시간이며, 빌드를 할 경우 수정된 시간은 Make에게 중요하게 영향을 미친다.
2. order-only-prerequisites
위와 상관없이 강제로 순서대로 실행하는 방법이다.
https://www.gnu.org/software/make/manual/html_node/Rules.html#Rules
http://korea.gnu.org/manual/4check/make-3.77/ko/make_4.html#SEC19
그리고, 이부분이 핵심이기에 이 부분은 따로 분리해서 설명하겠다.
https://www.gnu.org/software/make/manual/html_node/Recipes.html#Recipes
2.2 Make의 기본규칙
Make의 기본구성과 그 사용법을 알았으니, 자세한 동작방식에 대해 알아보자
이를 알아보려면, Make 내부에서 암묵적으로 사용하되는 변수들을 알아야한다.
주의사항이 이 내용은 filename에만 적용이 되고, shell에 의존적이다.
TEST를 위해 아래와 같이 구성했다
https://www.gnu.org/software/make/manual/html_node/Wildcards.html#Wildcards
많은도움을 받는다.
https://wiki.kldp.org/KoreanDoc/html/GNU-Make/GNU-Make-8.html
https://www.gnu.org/software/make/manual/html_node/Appending.html#index-appending-to-variables
https://www.gnu.org/software/make/manual/html_node/Shell-Function.html#Shell-Function
공통된 규칙은 '$'로 시작이되며, target과 prerequisites 을 기준으로 이 변수를 사용을 한다.
사용되는곳은 recipe에서 주로 적용하여 사용한다.
사실 매번 사용법을 잊어버려 Manual을 보기때문에, 자세한 내용은 Manual을 보자.
주의사항은 prerequisite은 동작모드가 2가지 모드이니 이부분을 잘 이해하고 보기바란다.
https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html#Automatic-Variables
많이 사용되는 것 두개를 다루면 다른 Special Target은 Manual 참조
.POHNY : target 과 filename을 구분과 성능향상을 위해서 사용
.SUFFIXES : The prerequisites of the special target, 즉 prerequisites의 접미사 규칙
https://www.gnu.org/software/make/manual/html_node/Special-Targets.html#Special-Targets
https://wiki.kldp.org/KoreanDoc/html/GNU-Make/GNU-Make-3.html
특히 임베디드에서는 이부분을 별도로 설정을 해야한다.
https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html#Implicit-Variables
정확히 말해 Suffix 의 Pattern을 변경할때 필요하다.
GNU Make or Make의 기본구성은 3가지로 구성 되며, 각 용어와 구성내용을 알아보자.
Makefile 분석을 하면 항상 기본형태는 아래와 같이 구성이 되며, 세부내용들은
천천히 메뉴얼과 함께 봐야할 부분들이다.
- targets : targets 으로 말하며, file name도 있으며, 일종 함수 같은 존재
- prerequisites : 현재 targets의 recipe를 실행하기전에 다른 targets 들을 순차적으로 호출
- recipe : 실제 동작하는 기능이며, command 및 shell script 내부구현.
targets : prerequisites recipe … # prerequisites는 스페이스로 구분자를 사용한다. targets : prerequisites ; recipe recipe .... # 세미콜론은 prerequisites 의 종료를 의미한다.
- Simple Test Example
TARGET = MainTest # Makefile안에 변수가 사용이 가능 # 변수는 암묵적으로 사용가능한 변수도 존재 CFLAGS, LDFLAGS OBJS = tst1.o tst2.o # tst1.o tst2.o tst1.c와 tst2.c의 filname이며, target 지정가능 # Make 내부에 기본적으로 설정된 규칙이 있으며, SUFFIX 및 PATTERN에 의해 변경가능 # 작성자가 규칙과 세부설정을 선언하지 않았다면 기본규칙처리 # make를 실행하면 기본으로 all이 실행된다. all: $(TARGET) # $(OBJS)는 prerequisites들 중 하나이므로 먼저 실행 한다 . 최종 $(TARGET) 실행한다. # $(TARGET): $(OBJS) @echo --------------------------------- @echo Test Result Program @echo --------------------------------- @echo $? # # $? 는 The names of all the prerequisites 이므로, tst1.o , tst2.o 출력 # clean: @rm -rf *.o # @ 는 echo의 실행화면을 감춘다.
https://www.gnu.org/software/make/manual/html_node/Rule-Syntax.html#Rule-Syntax
2.1 Make의 기본구성의 규칙
Make의 Rule은 위에서 언급한 target prerequisites recipe 의 다양한 기능과 구조를 익히면될것 같다.
자세한 내용은 아래의 링크된 Manual을 참조
- target 의 다양한 기능
target의 특정목적의 target도 존재하니 이부분도 익혀두자.
- prerequisites의 기능 및 자동기능
normal-prerequisites | order-only-prerequisites
1. normal-prerequisites
target 보다 먼저 순서적으로 prerequisites 진행하지만, 종속적인 관계를 유지하고
prerequisites가 target 보다 시간적으로 새거라면 현재 target은 쓸모가 없어지고 동작되지 않는다.
쉽게말해서 빌드 할경우 수정하지 않은 파일을 빌드하지 못하게하는 기능이라고 생각하면된다.
위에서 의 기준은 항상 시간이며, 빌드를 할 경우 수정된 시간은 Make에게 중요하게 영향을 미친다.
2. order-only-prerequisites
위와 상관없이 강제로 순서대로 실행하는 방법이다.
https://www.gnu.org/software/make/manual/html_node/Rules.html#Rules
http://korea.gnu.org/manual/4check/make-3.77/ko/make_4.html#SEC19
- recipe 의 규칙
그리고, 이부분이 핵심이기에 이 부분은 따로 분리해서 설명하겠다.
https://www.gnu.org/software/make/manual/html_node/Recipes.html#Recipes
2.2 Make의 기본규칙
Make의 기본구성과 그 사용법을 알았으니, 자세한 동작방식에 대해 알아보자
이를 알아보려면, Make 내부에서 암묵적으로 사용하되는 변수들을 알아야한다.
- Make 내부에서 Filename에서 wildcard 사용법
주의사항이 이 내용은 filename에만 적용이 되고, shell에 의존적이다.
TEST를 위해 아래와 같이 구성했다
$ ls Makefile build clean cst.c dst.c est.c print1 tst1.c tst11.c tst2.c tst22222.c tst3.c // *.c 는 전부 동일한 file 로 구성, build clean print1 는 diretory 이는 PHONY Target을 테스트 $ cat tst1.c // 전부 동일한 file들 #includeint test01() { printf("TEST 01 \n"); return 0; }
$ vi Makefile all: build ## filename or directory 와 구분 및 성능 향상이용 .PHONY: print1 print2 print3 build clean ### 규칙에 적용될 filename SRC1 = *.c ## wildcard '*' , 모든 filename SRC2 = $(wildcard *.c) ## Make 내부함수이용 $(SRC1) 동일 SRC3 = tst?.c ## wildcard '?' , filename 중 한 charter 선택 SRC3 ?= cst*.c ## SRC3 변수가 선언이 안되었다면 설정이 된다. SRC5 += $(SRC3) est*.c SRC6 += $(SRC3) dst*.c # 고급스럽게 ,shell 이용해보자. FILES := $(shell echo *.c) # build를 하기 위해서 모든 *.c를 *.o로 변경 # 아래와 같이 $(var)에서 pattern을 replaements로 변경한다. # $(wildcard *.c) 모든 *.c를 에서 %.c ->%.o 로 변경 # # $(patsubst pattern,replacement,$(var)) OBJS = $(patsubst %.c,%.o,$(wildcard *.c)) # *.c를 *.o로 변경 ## wildcard '*' , 모든 filename clean: @rm -f *.o # print1 과 print2 는 결과 동일 print1: ${SRC1} @echo $? print2: ${SRC2} @echo $? # @cat $? # tst1.c tst2.c tst3.c print3: ${SRC3} @echo $? # @cat $? # tst1.c tst2.c tst3.c est.c print4: ${SRC5} @echo $? # tst1.c tst2.c tst3.c dst.c print5: ${SRC6} @echo $? # print1,2와 동일 files: ${FILES} @echo $? # buld *.o로 변경이 되었기 때문에 build build: ${OBJS} @echo $?
https://www.gnu.org/software/make/manual/html_node/Wildcards.html#Wildcards
- 기본예제
- 에러처리 (중요)
많은도움을 받는다.
https://wiki.kldp.org/KoreanDoc/html/GNU-Make/GNU-Make-8.html
- Make 의 변수 설정 및 추가
https://www.gnu.org/software/make/manual/html_node/Appending.html#index-appending-to-variables
https://www.gnu.org/software/make/manual/html_node/Shell-Function.html#Shell-Function
- Make 의 Automatic Variables (자동변수)
공통된 규칙은 '$'로 시작이되며, target과 prerequisites 을 기준으로 이 변수를 사용을 한다.
사용되는곳은 recipe에서 주로 적용하여 사용한다.
사실 매번 사용법을 잊어버려 Manual을 보기때문에, 자세한 내용은 Manual을 보자.
주의사항은 prerequisite은 동작모드가 2가지 모드이니 이부분을 잘 이해하고 보기바란다.
- $@ : The file name of the target of the rule. (반드시 알아두자)
- $% : The target member name
- $? : The names of all the prerequisites
- $< : The name of the first prerequisite
- $| : The names of all the order-only prerequisites
https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html#Automatic-Variables
- Make의 Special Target
많이 사용되는 것 두개를 다루면 다른 Special Target은 Manual 참조
상위에서도 간단하게 작성했지만, target의 이름과 동일한 filename or directory가 존재한다면,
make가 문제가 생긴다. 이를 방지하고자 사용하며, 이를 이용하면, 이를 체크할 필요가 없기에 성능이 향상이 된다.
.SUFFIXES : .c .o .SUFFIXES : .cpp .o ## 본인이 정의 하면 된다. .c.o: ## 이와 같이 직접 정의 해줘도 정의 해줘도 되며, 세부설정이 가능하다. $(CC) $(CFLAGS) $(INC_DIR) -c $<
https://www.gnu.org/software/make/manual/html_node/Special-Targets.html#Special-Targets
https://wiki.kldp.org/KoreanDoc/html/GNU-Make/GNU-Make-3.html
- Make의 빌드에 관련된 변수 (Implicit-Variables)
특히 임베디드에서는 이부분을 별도로 설정을 해야한다.
https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html#Implicit-Variables
- Make의 Pattern Rule
정확히 말해 Suffix 의 Pattern을 변경할때 필요하다.
Pattern Rule만 소개
https://www.gnu.org/software/make/manual/html_node/Pattern-Rules.html#Pattern-Rules
Old Style Pattern 규칙
https://www.gnu.org/software/make/manual/html_node/Suffix-Rules.html#Suffix-Rules
2.3 Make의 기능의 확장
상위에서도 간단하게 사용했지만, GNU make 내부에 함수가 존재하며, 아래와 같이
이를 이용하면 편한하게 Make 작성이 가능하다.
- Make 내부 안에서 사용가능한 함수 (중요)
$(subst from,to,text) // 대체하는 함수 $(subst ee,EE,feet on the street) // fEEt on the strEEt’, ee->EE 대체
$(filter pattern…,text) // filter 역할함수 sources := foo.c bar.c baz.s ugh.h foo: $(sources) cc $(filter %.c %.s,$(sources)) -o foo // foo.c bar.c baz.s 만 빌드
$(foreach var,list,text) // shell script의 반복문과 유사하다 , text는 결과로 생각하면 되겠다. dirs := a b c d files := $(foreach dir,$(dirs),$(wildcard $(dir)/*)) // a/* b/* c/* /d*
https://www.gnu.org/software/make/manual/html_node/Functions.html#Functions
- Make 내부의 조건문 (변수와 함께 사용)
ifeq ($(CC),gcc) $(CC) -o foo $(objects) $(libs_for_gcc) else $(CC) -o foo $(objects) $(normal_libs) endif
https://www.gnu.org/software/make/manual/html_node/Conditionals.html#Conditionals
https://www.gnu.org/software/make/manual/html_node/Conditional-Example.html#Conditional-Example
https://www.gnu.org/software/make/manual/html_node/Conditional-Syntax.html
3. Make의 recipe 구현
make의 recipe는 실제의 동작이며, 가장 중요한 부분이기에 어떻게 사용할 것인지,
응용은 어떻게 할것인지에 대해 좀 자세히 알아보자
3.1 recipe의 Linux command 적용
Linux 내부에서 사용되는 다양한 command를 이용하여, Make 에 적용하는 방법이다.
가장 많이 사용하는 command를 아래와 같이 구성했으며, 이를 보고 간단히 구현을 해보자.
@는 command의 실행을보여주지 않는다.
`` 먼저 이 command를 실행한 후 결과를 연결해준다. (파이프 개념) (stdout -> stdin)
export를 이용하여 변수에 할당 및 변수값 조정을 했었는데, 이부분은 지금 힘든것 같다.
(다른방법으로 찾아보자, 가능하면 user mode에서 해결하자 )
$ vi Makefile test: @echo finished sub direcory clean: @rm -rf *.o install: install -d $(DESTDIR) ## 존재하지 않는 디렉토리 생성 install ./MainTest $(DESTDIR) ##생성 후 이를 이 디렉토리에 복사 test-version-recur1: @echo Building other program1 ##다른 Make program 관리 @cd test-rec; cd `find . -name "*test*"`; make CROSS_COMPILE=$(CROSS_COMPILE) test-version-recur2: @echo Building other program2 ##다른 Make program 관리 make -J 2 -C $(TEST_PATH)/test-* ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) ## @을 사용하면, 사용하는 command 실행되는 과정을 안보이게 할수 있다.
3.2 Make의 recipe 에 script 적용
Shell Script의 기능을 Make 안에 적용하는 것이지만 변수 사용법 이부분은 아래의 변수사용법 참조
이를 이용하면 좀 더 복잡하고 정교한 Make를 만들 것이 가능하다.
이 뿐만 아니라, sed , awk 등 다양한 것을 적용가능하다.
기본 Script를 익혀서 이를 Makefile 내부에 적용을 해보자
- 주의 및 확인사항 ( 반드시 확인 )
- 보통 line이 길어지는 '\'을 사용하여 다음줄로 한다. 이때 '\' 다음에 \n로 하고 빈공간을 없애자.
- Script 내부에 세미콜론(;)을 주의하자
- Makefile은 탭이 중요하기때문에 다시 확인하자
- Script 실행되는 것을 되는것을 보이지 않게하려면 @사용하여 전체를 가리자.
- Loop 문의 구분자, 즉 변수들을 구분하는 구분자는 스페이스이다.
그리고 위에서 설명했듯이 Loop의 List 변수의 구분자는 스페이스 이다.
- Recipe 안의 변수 사용법
https://www.gnu.org/software/make/manual/html_node/Variables-in-Recipes.html
A. For Loop 예제-1 (recipe 안에서 $$사용)
- $SUB_DIRS에서 하나씩 가져와서 dir 변수를 사용하여 반복되는 Loop문 구조
- @을 한번사용하여 전체적용
@for dir in $(SUB_DIRS); do \ $(MAKE) -C $$dir clean; \ done
B. For Loop 예제-2
아래와 같이 1 2 3의 구분자는 스페이스이다.
- 상위와 같지만, 1,2,3을 직접넣어 변수 i에 작동하는 Loop 구조
- @을 하나를 사용하여 전체 적용하여, 변수는 $${i} or $$i로 사용
@for i in 1 2 3; \ do \ echo TEST$${i}_$$i ; \ done
C. For Loop 예제-3
- 상위와 기본구조가 같지만 이중루프로 동작
- @을 한번사용하여 전체적용
@for i in 1 2 3; \ do \ for j in 1 2 3 4 5; \ do \ echo TEST$${i}_$$j ; \ done; \ done
D. IF문 및 EXIT 예제-1 (File 및 Directory 존재 여부 확인)
- if 문 File 및 Diretory으로 점검하는 구조
- exit 1는 에러로 표시하여 추후 재귀호출시 에러점검.
@if [ -f test]; then \ echo "You have test file \ else \ echo You have no test file \ exit 1; fi @if [ ! -d $(DIR) ]; then \ echo "You have no test directory \ fi @if [ -e $(FILE) ]; then \ echo "You have test file \ fi @if [ -d test]; then \ echo "You have test directory \ else \ echo You have no test directory \ exit 1; fi
- IF/LOOP및 기타 기본예제
http://egaoneko.github.io/os/2015/05/24/linux-starter-guide-8.html#fnref:1
- IF/CASE 예제
- Bash Script 여러예제
- Bash Loop/awk 활용
4. GCC의 다양한 Option 설정
이부분은 상위 Implicit-Variables 와 연관이 있으며 Make 내부에 GCC의 옵션 변경을 할때 아래와 같이 GCC Manual을 이용하여 설정을 변경하자
아래의 GCC 옵션들은 GCC-5.4.0 기준이며, 본인이 사용하는 GCC version에 맞추어
문서를 찾아 Index를 찾으면 될 것이다.
- Index 주의사항
https://gcc.gnu.org/onlinedocs/gcc-5.4.0/gcc/Option-Index.html#Option-Index
- ARM 용 별도의 option
5. Make의 관련 다양한 예제
Make의 기본 기능은 Target과 그의 종속된 Target 을 연결하여 실행하는 것이다.
그리고, Make를 재귀적용법으로도 실행을 하여 다른 Makefile을 제어도 가능하다.
- Simple Makefile
- 사용목적과 기본사용방법
https://www.joinc.co.kr/w/Site/C/Documents/minzkn_make
http://developinghappiness.com/?p=28
- Make의 재귀적 용법사용
- 일반적으로는 make -C 옵션을 주어 내부에서 재귀적으로 호출한다.
- 다른방법은 cd로 직접 해당주소로 가서 make를 실행을 한다.
- Make의 재귀적 용법의 다양한 예제
6. GNU Make Manual 관련사항
- GNU Make의 전체 Manual
http://korea.gnu.org/manual/4check/make-3.77/ko/make_toc.html
https://wiki.kldp.org/KoreanDoc/html/GNU-Make/GNU-Make.html#toc8
GNU Make의 Manual 내용이 많다보니, 상위 Manual에서도 아래와 같이 읽어보라고 권하고 있다.
- GNU Make의 Manual
- Introduction : 소개
- Features : 기본 기능
- Incompatibilities and Missing Features : 비호환성과 빠진 기능
- Special Target : 내부에 암묵적으로 사용가능한 Target
- Quick-Reference: Make에 익숙하다면, 많이 도움이되는 Page
- Options-Summary: Make의 재귀를 사용시 Make의 option 기능을 알수 있다.
https://www.gnu.org/software/make/manual/html_node/Features.html#Features
https://www.gnu.org/software/make/manual/html_node/Missing.html#Missing
https://www.gnu.org/software/make/manual/html_node/Special-Targets.html#Special-Targets
https://www.gnu.org/software/make/manual/html_node/Quick-Reference.html#Quick-Reference
https://www.gnu.org/software/make/manual/html_node/Options-Summary.html#Options-Summary
- GNU Make Index
7. Kernel Makefile 관련내용
Kernel Makefile을 보면 상위부분은 복잡하지만, 밑으로 갈수록으로 모듈화가 잘되어있어
사용하기가 편하다.
U-Boot Makefile 역시 비슷하지만 다르게 구성이 되어있지만, 유사한 부분이 많이 있다.
솔직히 Kernel Makefile과 U-Boot Makefile은 수정할 일이 거의 없으며 간단한 Config 규칙과 Makefile 추가하는 식을 알면된다.
- obj-y obj-n -obj-m 설정
https://www.kernel.org/doc/Documentation/kbuild/makefiles.txt
피드 구독하기:
글
(
Atom
)