2/28/2016

autoconf automake aclocal, autoheader,

최근들어 Autoconf와 Automake 및 관련사항을 잘 다루지 않으며, 거의 사실 사용할 일이 없어, 아래와 같이 Link만 연결한다.

  • Autoconf Manual
  https://www.gnu.org/software/autoconf/manual/autoconf.html

2/27/2016

Linux RC Script 와 /etc/network/interfaces 분석

Linux Init Script로 배포하는 곳마다 다르며, 지속적으로 변화 중인 것 같아  간단히 기록한다.
아래와 같이 간단히 동작부분을 확인만 하자


#! /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들을 알아두록하자. 

  • Audio 관련 부분 전체 Index
TI에서 제공해주는 Audio 관련 ALSA Guide로 현재 AM38xxx 와 DM84xx 를 위해서 변경사항이 있는지 확인만 하자 

  • ALSA Common API
ALSA의 일반적인 API로 아래 함수명과 설명을 보면 쉽게 사용법이 짐작이 간다. 
관련 세부내용들은 생략하도록 하겠다. 
Commonly Used APIs
NameDescription
snd_pcm_openOpens a PCM stream
snd_pcm_closeCloses a previously opened PCM stream
snd_pcm_hw_params_anyFill 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_paramsInstall one PCM hardware configuration chosen from a configuration space
snd_pcm_writeiWrite interleaved frames to a PCM
snd_pcm_readiRead interleaved frames from a PCM
snd_pcm_preparePrepare PCM for use
snd_pcm_dropStop a PCM dropping pending frames
snd_pcm_drainStop a PCM preserving pending frames


아래의 ALSA의 Playback or Capture도 간단하게 짜기 싫다면, ALSA Tool을 간단하게 이용하도록하자. 

1.1 ALSA의 PLAYBACK FLOW


ALSA를 이용하여 기본적으로 Playback하는 flow로 그리 어렵지 않으며 거의 다른 일반 Linux System Call과 거의 유사하다. 

  1. Playback Mode로 Open
  2. hw parameter 관련설정 (format/acess type/ sample rate/ channel )
  3. write로 재생시작 


1.2 ALSA 의 CAPTURE FLOW


상위와 동일 
  1. Capture Mode로 Open
  2. hw parameter 관련설정 (format/acess type/ sample rate/ channel )
  3. read로 녹음시작 


관련내용출처 

2/25/2016

Linux Network 설정

1. Linux Network 설정 

이부분의 동작방식은 다시 boot script 부분을 보면 동작하는 방식을 이해가능

  • /etc/network/interfaces  설정의 예제 
  http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/System_management/NetworkConfiguration
  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로 가면 전체구조가 변경이 될 수도 있겠지만, 
거의 근본적으로 구성은 AP/SoC의 관련 Driver 만들어서 ALSA Interface에 맞게 연결하여 동작하는 구조가 비슷하므로, 관련부분을 알아보도록하자.

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 관련 부분 설명 
아래의 Link는 보면, 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의 기본구조 설명  
      http://processors.wiki.ti.com/index.php/Sitara_Linux_Audio_Driver_Overview
   

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 
PCM Interface Driver로 , Platform Driver 라고 부른다. Machine Driver와 연결이 되어 있으며, PCM의 관련처리를 이곳에서 처리한다.
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
TI사에 제공하는 SOC Driver (McBSP)이며, 이는 PCM Interface Driver와 같이 동작하며,실질적인 SoC의 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
아래의 사이트를 보면, 각 CPU 마다 Driver의 구조 및 FLOW  ,구조를 설명을 하고 있다.
  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 확인 
linux kernel log에서 아래와 같이 ALSA device에 추가 되었는지 확인을 하자.
DM368인 경우, TLVAIC3x 코덱을 사용을 하면, 2개의 McBSP Driver의 충돌로 인하여 제대로 등록이 되지 않는다.

ALSA device list:
             #0: DaVinci DM365 EVM


  • ALSA Card 등록확인
ALSA에 등록하여 사용하도록 하자 
$ 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-mcbsp platform_device를 등록을 하였지만,이 platfor_driver가 현재 두개가 존재하여 문제가 됨
이중  davinci-i2s.c  선택하여 사용함
  1. ./sound/soc/davinci/davinci-i2s.c     // 이 McBSP는 일반 Codec 사용
  2. ./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 명이라 생각하면되겠다.

  • Eclipse Neon Dowload
  C/C++ 용 Eclipse용으로 아래의 절차대로 설치를 해보자.
  https://www.eclipse.org/downloads/

  • Eclipse CDT Download 
  CDT(C/C++ Development Tooling)로 Eclipse는 개발 Tools이지만 Compiler 가 필요하다.
  https://eclipse.org/cdt/

  • 관련설치 
  http://blog.xcoda.net/89


1.1 Eclipse Neon 설치시, Java JDK 설치  
      
       WIN 64bit :   jdk-7u79-windows-x64.exe   Download 및 설치





  • 설치후 문제사항 
       ERR MSG: could not create the java virtual machine





  • 수정사항
       C:\Users\JHLEE\eclipse\cpp-neon\eclipse\eclipse.exe\eclipse.ini


저의문제는 JDK Version 문제 였으나, 아래와 같이 RAM Size 문제일 가능성도 있을 것 같다

-Xms256m
-Xmx1024m

  http://dkatlf900.tistory.com/93

1.2 Eclipse CDT 설치 후 화면확인  

크로스 컴파일러를 설치가 되어 있어야 제대로된 동작이 가능한 것 같다.

  • Eclipse 설치 후 확장기능 
       설치후 기본 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를 이용하여 이클립스와 연동하여 사용하는 것이 주 목적이다.

  • Download (Cygwin)설치 
  http://www.cygwin.com/
  상위 Cygwin에 MingGW도 포함 

  • MingGW 참고  
  http://www.mingw.org/
  http://rinovation.tistory.com/2
  https://www.eclipse.org/forums/index.php/t/1073505/


2. Cygwin 설치 및 재설치 

Cygwin은 윈도우의 제어판에서 프로그램 제거를 할 수가 없다.
설치시 이부분을 정확하게 인지하고 있어야한다.

setup-x86_64.exe 을 다시 실행하여 필요한 Package를 추가하여 재설치가 가능하다

  • Cygwin 설치방법 및 재설치 
setup-x86_64.exe를 실행을 하여 설치를 진행을 한다.






상위 그림에서 패키지를 제공해주는 사이트는 많으므로, 사이트를 아무거나 선택하자


상위 상단 좌측의 View를 Category로 변경 후
Devel에서 필요한 것들이 있다면 설치  Cross Compiler (Cygwin or Mingw64)


Net->openssh  및 ssh library 설치 ( 소스는 제외)


  • Cygwin 설치후 SSH 동작확인 
Cygwin64 Terminal을 이용 or Windows의 CMD 명령이용(하단의 PATH를 추가 한후)
설치된 Package를 실행



2.1 Cygwin 제거방법 

위에서 설명했듯이 Cygwin은 제어판의 프로그램에 나오지 않아서 직접삭제를 해야한다.
그리고, Cygwin에서 사용하고 있는 파일과 데몬이 있다고 중지를 하고 삭제를 진행을 해야한다.

regedit를 이용하여 레지스트리를 편집을 하고, 가능하면 편집의 찾기를 이용하여 찾자
Cygwin or Cygnus Solutions



아래의 Cygnus Solutions에서 Cygwin으로 삭제

  1. HKEY_LOCAL_MACHINE\SOFTWARE\Cygwin
  2. HKEY_CURRENT_USER\Software\Cygwin
  3. HKEY_USERS\.Default\Software\Cygwin  (현재 없음)


  http://infoarts.tistory.com/25

3. Cygwin 명령어와 Window 공유 (Eclipse 와 공유)

    1. Window Key + Pause/Break 
    2. 고급시스템 설정 선택 (좌측메뉴)
    3. 시스템속성창 의 고급->환경변수 선택 (맨아래에 위치) 
    4. 환경변수창이 아래의 시스템변수  PATH 선택 
    5. 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와 같이 구성할 것이므로, 아래의 참조내용을 이해하고 사용하자.
    • 빌드서버와 Eclipse 기본환경구성이해 
      https://ahyuo79.blogspot.com/2016/02/eclipse.html
    • Eclipse CDT 설치 및 확장 
      https://ahyuo79.blogspot.com/2016/02/eclipse-neon-cc-cdt.html
    • Window에 Linux Tool 설치 
      https://ahyuo79.blogspot.com/2016/02/eclipse-neon-cc-cygwin.html

    상위구성이 되었다면, 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 창설정
    1. Window->Show View->Other  선택 
    2. General->Project Explorer  설정



    1.1 Project 기본생성 및 제거 

    • 프로젝트 생성 및 C/C++ Indexer 생성
    기존 Linux Code를 찾아 이곳에 등록을 하고 Project를 새로 생성을 하자 
    1. File->New->Project 
    2. Makefile Project with Existing Code 선택
    3. None or Cross GCC 선택 






    생성과 동시에 우측 하단에 Refreshing Working Space라고 하며 진행이 되며 보통 Index도 함께 생성이 된다.

    • 프로젝트 제거 
    만약 제거하고 싶다면 아래와 같이 생성된 Project에서 Delete를 하면 제거가 가능하다



    2. Eclipse의 설정  

    Eclipse의 설정들은 아래와 같이 구성이 되며, Project Properties의 경우는 세부 설정이며 Project 마다 변경이 될 수 있다.
    하지만 Window->Preference의 경우는 전체 설정이라고 생각하면 될 것이다.

    1. Window->Preferences
    2. Project의 Properties


    2.1 Project의 Properties

    이제 생성된 Project의 세부설정을 변경하고 싶다면 아래와 같이 둘 중 하나만 하면된다.
    1. Project->Properties 선택 
    2. Project Explorer 창에서 Project 선택 후 우측 클릭 Properties 선택 
    만약 활성화가 되지 않았다면, 왼쪽 Project Explorer에서 Project를 선택을 하면 활성화가 된다.

    • Resource  확인사항 
    각 파일의 Encoding을 변경가능하며 한글에 민감한 부분이므로 주의해서 사용하자
    UTF-8 / MS949
    MS949가 없다면 Window->Preferences의 General 의 Workspace 부분을 한번살펴보자
    다른부분은 한번 살펴보자


    3. 원격 Build 설정 (Project Target) 설정

    Window의 Eclipse에서 SSH를 통하여 Linux Build Server에서 Source를 Build를 하기위해서 다음과 같은 설정필요
    1. cygwin의 openssh 설치필요 
    2. cygwin의 ssh 설정 필요 ( SSH 암호 없이 로그인이 가능하도록 설정)


    • Window에 Linux Tool (Cygwin의 SSH기능 설치) 
      https://ahyuo79.blogspot.com/2016/02/eclipse-neon-cc-cygwin.html


    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 창 설정  (상위 좌측의 그림설정)

    1. Target Name:  이클립스에서 보기위한 Target Name (e.g uboot)
    2. Make Target: 실제 Makefile의 Target Name (Window의 Makefile을 아니므로, 사용안함)
    3. 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 의 아래 Build를 눌러 cygwin의 ssh를 이용하여 Build를 적용하면 Console에서 확인가능

    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 및 편의기능 설정
    1. Window->Editor->Toggle Split Editor  ( 화면분할)
    2. Window->Show View->Remote System
    3. Window->Preference  ( 기타 모든 설정)

    • VI관련 기능 
    Linux에서는 편집기를 VI or emacs를 사용해야하지만, Eclipse에서 이를 편하게 하기위해서는 vrapper 설치하면 된다고 하지만 유용성은 그다지 인것 같다.
    이것을 사용하는 목적은 순전히 ctags 기능때문이지만 이용할수 없다고 하니 별다른 도움이 되지 않을 것 같다.
    1. Help->Install New Software 
    2. 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가 제공이 된다.
    1. SSH Client  기능 
    2. SFTP Client 기능  (윈도우 탐색기 처럼 사용가능하나 불편함 )
    3. Local Files->Drivers 이용 (Samba로 Window에서 Network Driver로 연결)

    위의 3가지 기능을 사용하면, Virtualbox의 Server와 편하게 SSH를 접속할 수 있을 뿐만 아니라,
    SFTP를 이용하여 윈도우의 탐색기 기능처럼 사용이 가능하지만 기능이 제한적이다.
    그래서, 가급적이면 SFTP하려고 한다.
    참으로 좋은 개발 Tool이며 편한 것 같다.

    현재 XShell을 사용을 하고 있지만, Eclipse도 꽤 괜찮은 것 같다고 생각이 들지만, XShell 보다 좀 불편해서 그냥 Xshell을 별도 사용중이다.

    XShell 역시 위 두 기능을 제공하고 있다. (SSH 와 SFTP 기능 )
    • Remote System 설정방법
     SSH와 SFTP 설정은 다음과 같이 진행을 하면된다. 그림은 아래를 참고하면된다.
    1. Window->Perspective->Open Perspective-> Others -> Remote Systems Explorer 선택  
    2. 생성된 Remote System의 좌측의 맨위 아이콘 (Define a connection to remote system) or 마우스 우측 클릭 후, new->connection를 선택 
    3.  SSH Only 선택 후 본인의 SSH Server 관련 설정 

    • Remote System에서 new->connection 선택 ( 상위 1번동일 )



    • SSH Only 설정 및 관련 설정 (상위 2번 동일)


    • SSH를 설정하면, 자동으로 SFTP도 설정이 됨 (상위 3번 동일)



        vi 편집기를 이용하는데, ssh를 이용하여 편하게 eclipse에서 편집이 가능하다.
        다만 설정을 UTF-8로 변경을 해줘야 한다.

    • SSH에서 한글깨짐문제 
    1. Window>Preferences 선택 
    2. General>Workspace  선택 
    3. 아래메뉴의 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에러인것 같다.


     $ 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 설정 
    일반적으로 Kernel의 옵션을 설정할때 menuconfig를 사용하지만,
    다양한 설정 방법이 존재한다.

    make menuconfig  // 일반 설정
    
    make xconfig  (gconf  tool 사용) , QT (KDE) based GUI Kernel config
    
    make gconfig  (gkc tools )    GTK , GNOME
    
    
      https://www.halolinux.us/fedora-7-reference/kernel-configuration-tools.html

    2/16/2016

    Audio-ALSA SOC Framework-Codec Driver ( Kernel)

    1. Hardware 기본구성 및 설정

    • 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 */
    

    가장 일반적인게 I2S이며, DSP Mode A/B 혹은 AC97인데, Codec Chip이 지원되는 거에 따라 변경해서 사용하자. 

    • 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 
    아래는 AIC3100이 DSP MODE Interface방식이며, 이는 McBSP or McASP와 같이 설정을 확인해봐야한다.
    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 예제이며 구조는 다음과 같다.
      1. module init 이 호출되면서, i2c_add_driver 호출하여, i2c driver 를 등록
      2. 이미 등록된 I2C device가 있으면, 이를 찾아 probe를 호출 (platform_driver 구조와 동일)
      3. aic3x_i2c_probe 는 snd_soc_register_codec 사용하여 Codec Driver를 등록한다.
      4. 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에 포함이 되어있지 않다면, 아래와 같이 직접 연결하여 사용해야한다.

      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 인 경우 
      아래와 같이 Codec Driver의 CPU Driver의 set_fmt 설정 하고, Codec Driver의 sys_clk을 호출하여 설정한다.

      $ 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 Format? 이 존재하고 각 AP/SoC 업체들은 각 자신들의 BSP Driver를 이 Format에 맞추어 동작가능하도록 하고 호환성을 높인다. 

      1.1 OSS와 ALSA 

      OSS (Open Sound System) 약어로 Linux 2.4에서 공식적으로 사용을 했다고 한다.이때도 Audio Driver 수정했지만, 모르고 수정했다.
      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는 다음과 같으며, 위와 같다.

      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)

      • 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)

      • ALSA PCM 기본설명
        http://www.alsa-project.org/alsa-doc/alsa-lib/pcm.html
        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들
      ex) gstremer, sndlib 등 native version에 따라 지원되는 app이 다르다.
        http://www.alsa-project.org/main/index.php/Applications
      Android로 가면, Hal이 될수도 있다.

      • ALSA Test (alsa-utils)
      ALSA Test program (aplay, arecord, amixer )
        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 소스를 확인이 가능하며, 아래와 같이 빌드하여
      간단히 만들고 이 프로그램을 테스트 용도로 사용해보자.


       $ 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 이 존재하며,
      1. i2cdetect
      2. i2cdump
      3. i2cset
      4. 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 내부 규칙을 가급적 분리해서 알아야 두면 편하다.

      2.  Make의 기본구성 및 구조 

      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 
      다음은 내가 TEST 하기 위해 만든 간단한 예제이며, 각 내용을 주석으로  #로 표시하고  정리했다.

      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 는 wildcard 와 변수도 사용가능하며, 다중 target 등에 다양하게 사용이 가능하다.
      target의 특정목적의 target도 존재하니 이부분도 익혀두자.

      • prerequisites의 기능 및 자동기능 
      기본적으로 두가지 Type의 기능이 존재하며, '|'로 이를 구분한다.

      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 의 규칙 
      recipe의 기본 rule인 tab 과 항상 시작하는 것이고 중요한 것은 재귀용법인 것 같다.
      그리고, 이부분이 핵심이기에 이 부분은 따로 분리해서 설명하겠다.

        https://www.gnu.org/software/make/manual/html_node/Recipes.html#Recipes


      2.2 Make의 기본규칙 

      Make의 기본구성과 그 사용법을 알았으니, 자세한 동작방식에 대해 알아보자
      이를 알아보려면, Make 내부에서 암묵적으로 사용하되는 변수들을 알아야한다.

      • Make 내부에서 Filename에서 wildcard 사용법  
      Make의 내부에 기본 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 print1diretory 이는 PHONY Target을 테스트
      
      $ cat tst1.c // 전부 동일한 file들 
      
      #include
      
      int 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


      • 기본예제 
      Makefile의 간단한 예제이며, 사용하기 쉬운 기본예제
        https://wiki.kldp.org/KoreanDoc/html/GNU-Make/GNU-Make-7.html


      • 에러처리  (중요)
      Makefile을 만들다 보면 분명 에러가 발생한다 아래의 사이트를 참고해보자.
      많은도움을 받는다.
        https://wiki.kldp.org/KoreanDoc/html/GNU-Make/GNU-Make-8.html


      • Make 의 변수 설정 및  추가 
        https://www.gnu.org/software/make/manual/html_node/Setting.html#Setting 
        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가지 모드이니 이부분을 잘 이해하고 보기바란다.

      1. $@  : The file name of the target of the rule. (반드시 알아두자)
      2. $%  : The target member name
      3. $?  : The names of all the prerequisites
      4. $<  : The name of the first prerequisite
      5. $|  : 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 
      Make내부에서 사용되는 특별한 Target이며, 선언하여 이를 사용한다.
      많이 사용되는 것 두개를 다루면 다른 Special Target은 Manual 참조

      .POHNY :  target 과 filename을 구분과 성능향상을 위해서 사용

       상위에서도 간단하게 작성했지만, target의 이름과 동일한 filename or directory가 존재한다면, 
      make가 문제가 생긴다. 이를 방지하고자 사용하며, 이를 이용하면, 이를 체크할 필요가 없기에 성능이 향상이 된다.  

      .SUFFIXES : The prerequisites of the special target, 즉  prerequisites의 접미사 규칙

      .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)
      Make 내부에는 묵시적으로 빌드에 관련된 설정 및 옵션이 정해져 있지만 이를 본인 변경이 가능하다.
      특히 임베디드에서는 이부분을 별도로 설정을 해야한다.

        https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html#Implicit-Variables

      • Make의 Pattern Rule  
      Make 내부에는 묵시적으로 정해진 Pattern 규칙이 존재하지만, 이를 변경을 해야하는 경우가 많이 발생한다.
      정확히 말해 Suffix 의 Pattern을 변경할때 필요하다. 

      2.3 Make의 기능의 확장 

      상위에서도 간단하게 사용했지만, GNU make 내부에 함수가 존재하며, 아래와 같이
      이를 이용하면 편한하게 Make 작성이 가능하다.

      • Make 내부 안에서 사용가능한 함수 (중요)
        Make 내부에서 사용가능한 Macro 같은 함수로 다양한 함수를 제공하고 있다.

      $(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 내부에 적용을 해보자

      • 주의 및 확인사항 ( 반드시 확인 )
      1. 보통 line이 길어지는 '\'을 사용하여 다음줄로 한다. 이때 '\' 다음에  \n로 하고 빈공간을 없애자.
      2. Script 내부에 세미콜론(;)을 주의하자 
      3. Makefile은 탭이 중요하기때문에 다시 확인하자
      4. Script 실행되는 것을 되는것을 보이지 않게하려면 @사용하여 전체를 가리자. 
      5. Loop 문의 구분자, 즉 변수들을 구분하는 구분자는 스페이스이다. 
      아래의 예제들은 Makefile 안에 반드시 탭과 함께 넣어야 해야 동작을 한다.
      그리고 위에서 설명했듯이 Loop의 List 변수의 구분자는 스페이스 이다.

      • Recipe 안의 변수 사용법
        receipe 안에서 변수 사용할경우, 반드시 $$로 사용해야한다
        https://www.gnu.org/software/make/manual/html_node/Variables-in-Recipes.html


      A. For Loop 예제-1   (recipe 안에서  $$사용) 


      1. $SUB_DIRS에서 하나씩 가져와서 dir 변수를 사용하여 반복되는 Loop문 구조
      2. @을 한번사용하여 전체적용  

      @for dir in $(SUB_DIRS); 
      do \
           $(MAKE) -C $$dir clean; \
      done

      B. For Loop 예제-2

      아래와 같이 1 2 3의 구분자는 스페이스이다.
      1. 상위와 같지만, 1,2,3을 직접넣어 변수 i에 작동하는 Loop 구조
      2. @을 하나를 사용하여 전체 적용하여, 변수는 $${i} or $$i로 사용

      @for i in 1 2 3; \
      do \
            echo TEST$${i}_$$i ; \
      done

      C. For Loop 예제-3

      1. 상위와 기본구조가 같지만 이중루프로 동작
      2. @을 한번사용하여 전체적용

      @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 존재 여부 확인)

      1. if 문 File 및 Diretory으로 점검하는 구조
      2. 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://linuxcommand.org/wss0090.php
        http://egaoneko.github.io/os/2015/05/24/linux-starter-guide-8.html#fnref:1

      • IF/CASE 예제
        http://atcamp.co.kr/cosmos/solar/read.php?board=class&uid=13&cafeid=23

      • Bash Script 여러예제
        http://www.thegeekstuff.com/tag/bash-tutorial/

      • Bash Loop/awk 활용 
        http://www.thegeekstuff.com/2011/07/bash-for-loop-examples/?utm_source=feedburner


      4. GCC의 다양한 Option 설정 

      이부분은 상위 Implicit-Variables 와 연관이 있으며 Make 내부에 GCC의 옵션 변경을 할때 아래와 같이 GCC Manual을 이용하여 설정을 변경하자

      아래의 GCC 옵션들은 GCC-5.4.0 기준이며, 본인이 사용하는 GCC version에 맞추어
      문서를 찾아 Index를 찾으면 될 것이다.

      • Index 주의사항 
         '-' 이 제거가 되어있기에  ABCD 순서대로만 찾으면 된다.
        https://gcc.gnu.org/onlinedocs/gcc-5.4.0/gcc/Option-Index.html#Option-Index

      • ARM 용 별도의 option 
        https://gcc.gnu.org/onlinedocs/gcc-5.4.0/gcc/ARM-Options.html#ARM-Options


      5. Make의 관련 다양한 예제

      Make의 기본 기능은 Target과 그의 종속된 Target 을 연결하여 실행하는 것이다.
      그리고, Make를 재귀적용법으로도 실행을 하여 다른 Makefile을 제어도 가능하다.

      • Simple Makefile 
        http://korea.gnu.org/manual/4check/make-3.77/ko/make_2.html#SEC6

      • 사용목적과 기본사용방법
        최근에 찾은사이트로 기본사용법이 잘나와 있어 좋다.
        https://www.joinc.co.kr/w/Site/C/Documents/minzkn_make
        http://developinghappiness.com/?p=28


      • Make의 재귀적 용법사용
      1.  일반적으로는 make -C 옵션을 주어 내부에서 재귀적으로 호출한다. 
      2.  다른방법은 cd로 직접 해당주소로 가서 make를 실행을 한다. 
        https://www.gnu.org/software/make/manual/html_node/Recursion.html#Recursion



      6. GNU Make Manual 관련사항 

      • GNU Make의 전체 Manual  
          https://www.gnu.org/software/make/manual/html_node/index.html#SEC_Contents
          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 
        1. Introduction  : 소개 
        2. Features : 기본 기능 
        3. Incompatibilities and Missing Features : 비호환성과 빠진 기능 
        4. Special Target : 내부에 암묵적으로 사용가능한 Target 
        5. Quick-Reference:  Make에 익숙하다면, 많이 도움이되는 Page 
        6. Options-Summary: Make의 재귀를 사용시 Make의 option 기능을 알수 있다. 
          https://www.gnu.org/software/make/manual/html_node/Introduction.html#Introduction
          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
          https://www.gnu.org/software/make/manual/html_node/Concept-Index.html#Concept-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