Embedded Linux Picture Frame!

Hi,

In this article, I will talk about how to control IO ports using Embedded Linux platforms.

The platform which is used in this project is a edb9302 compliant development board. It has 16 MB Intel strata flash and 32 MB SD RAM, gpio connection in order to communicate custom design interfaces, for information about the development board, can be looked at this link;

http://www.cirrus.com/en/products/pro/detail/P1066.html

Briefly in this project , i have connected a elt240320atp LCD screen to the embedded Linux development board with a parallel gpio interface.

An interface software is written, in order to create communication between the embedded Linux development board and the elt240320atp LCD screen.

Let’s take a look interface software.

The program is designed to communicate with lcd screen can be split into two parts, gpio controller and elt240320atp lcd screen controller.

All right, how to open GPIO interface without using a device driver in a Embedded Linux platform?
Answer, using /dev/mem device.

/dev/mem device is a king of character device is used to access to physical memory via generic file manipulation system calls, for example; open, read, write, seek, close, etc.

As can be seen in the code snipe,

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
	iofd = open("/dev/mem", O_RDWR | O_SYNC);
	if (iofd == -1) {
		fprintf(stderr ,"\n%s\n", "Cannot open /dev/mem device!");
		return(errno);
	}
 
	ptrregisterbase = (unsigned char *) mmap(0, getpagesize(), PROT_READ|PROT_WRITE, \
					MAP_SHARED, iofd, 0x80840000 );
 
	ptrconfigbase   = (unsigned char *) mmap(0, getpagesize(), PROT_READ|PROT_WRITE, \
					MAP_SHARED, iofd, 0x80930000 );
 
	porta_dr  = ptrregisterbase+0x00;/*data register*/
	porta_ddr = ptrregisterbase+0x10;/*data direction register*/
 
	portb_dr  = ptrregisterbase+0x04;
	portb_ddr = ptrregisterbase+0x14;

In the code snipe above; main.c:line 64, /dev/mem device is opened as a character device. In case of cache mechanism of the MMU, O_SYNC is used in order not the MMU to cache the written data.

In the line 70 and 73, mmap function is used in order to map the file descriptor which is obtained by open function to the pointer to a integer.

EP9302-ELT240320ATP

figure.1: EP9302 - ELT240320ATP connection

As can be seen in the figure.1 sbc and lcd connected with each other.

ELT240320ATP

figure.2: ELT240320ATP, 320x240 TFT LCD

A picture is printed on the screen of the lcd, top left text is also printed as courier font.

Whole project code and pictures can be downloaded here.

Any kind of feedback or question is accepted gratefully.

Best Regards.

bolatdinc at gmail.com

Embedded Linux

Comments (0)

Permalink

How to use Subversion?

In this article, i will talk about installing and using Subversion on Ubuntu 10.04 LTS machine.

What is Subversion?
In brief Subversion is a kind of version tracking and common software development software.
You can easily develop your software projects by creating revisions using Subversion.

Now let’s install Subversion on our GNU/Linux machine, Ubuntu 10.04 LTS.

1-) Installing Subversion packages,

   bolat@bolat-vaio:~$ sudo apt-get install subversion libapache2-svn
 

2-) Creating subversion group and adding users,

   a-  Choose System > Administration > Users and Groups from your Ubuntu menu.
   b-  Select the Group tab.
   c-  Click the 'Add Group' button
   d-  Name the group 'subversion'
   e-  Add yourself (for me username: bolat) and www-data (the Apache user) as users to this group
        In order to see your user name and subversion group,
        - Start gconf settings editor: Alt+F2 gconf-editor Enter.
        - In the tree, locate /apps/gnome-system-tools/users.
        - Select the "showall" check-box.

3- Creating Subversion folder.

   bolat@bolat-vaio:~$ sudo mkdir /var/svn
   bolat@bolat-vaio:~$ cd /var/svn
   bolat@bolat-vaio:/var/svn $ sudo mkdir projects

4- Creating repository in the Subversion folder.

   bolat@bolat-vaio:~$ sudo svnadmin create /var/svn/projects

5- Configuring file permissions,

   bolat@bolat-vaio:~$ cd /var/svn
   bolat@bolat-vaio:/var/svn $ sudo chown -R www-data:subversion projects
   bolat@bolat-vaio:/var/svn $ sudo chmod -R g+rws projects

6- Importing projects into Subverion repository,

   bolat@bolat-vaio:~$ svn import /home/bolat/embedded/lpc2368projects file:///var/svn/projects

7- Configuring apache web server for WebDAV access, (You can easily access the subversion repositories through http, using WebDAV plugin)

   bolat@bolat-vaio:~$ sudo nano /etc/apache2/mods-available/dav_svn.conf

then add these lines below,

  <Location /svn/projects>
     DAV svn
     SVNPath /var/svn/projects
     AuthType Basic
     AuthName "myproject subversion repository"
     AuthUserFile /etc/subversion/passwd
     <LimitExcept GET PROPFIND OPTIONS REPORT>
        Require valid-user
     </LimitExcept>
  </Location>

or in order to see all repositories at once,

  <Location /svn>
     DAV svn
     SVNParentPath /var/svn
     SVNListParentPath On
     AuthType Basic
     AuthName "Subversion Repository"
     AuthUserFile /etc/subversion/passwd
     <LimitExcept GET PROPFIND OPTIONS REPORT>
        Require valid-user
     </LimitExcept>
  </Location>

then,

   bolat@bolat-vaio:~$ sudo /etc/init.d/apache2 restart

8- Adding users into authenticating WebDAV access,

   bolat@bolat-vaio:~$ sudo htpasswd -c /etc/subversion/passwd bolatsvnuser

not: must be used -c parameter, in order to create first user.

   bolat@bolat-vaio:~$ cat /etc/subversion/passwd

you can be sure that user added.

9- Trying Subversion repository,

   bolat@bolat-vaio:~$ svn co http://hostname/svn/projects projects --username bolatsvnuser

not: if you use for local machine, host name must be localhost instead of hostname.

10- Accessing methods Subversion repository,
Basic subversion access methods,

   - file://    Direct repository access (for local disk)
   - http://    Access via WebDAV protocol to Subversion-aware Apache2 web server
   - svn://     Access via custom protocol to an svnserve server
   - svn+ssh:// Same as svn://, but through an SSH tunnel

Direct access to Subversion repository from local,

   bolat@bolat-vaio:~$ svn co file:///var/projects

not: be careful about three slash,

   bolat@bolat-vaio:~$ svn co file://localhost/var/projects

Access to the repository via http:// WebDAV

   bolat@bolat-vaio:~$ svn co http://hostname/projects projects

Access to the repository via custom protocol svnserve server,

   bolat@bolat-vaio:~$ svn co svn://hostname/projects projects

Access to the repository via custom protocol svnserve through SSH tunnel,

   bolat@bolat-vaio:~$ svn co svn+ssh://hostname/projects projects

If you want to configure user access to Subversion repository,

   bolat@bolat-vaio:~$sudo nano /var/svn/projects/conf/svnserve.conf

then edit

# anon-access = read
# auth-access = write

section to allow anonymous and/or authoritative access.

If you would like to use proprietary svn access to Subversion repository, you must set svnserv as,

   bolat@bolat-vaio:~$ svnserve -d --foreground -r /path/to/repos
   # -d -- daemon mode
   # --foreground -- run in foreground (useful for debugging)
   # -r -- root of directory to serve

For more usage details, please refer to:

$ svnserve --help

Now we installed Subversion, imported a project, and configured Subversion access, let’s check it out,

   bolat@bolat-vaio:~$ svn co http://localhost/svn/projects -username bolatsvnuser
   bolat@bolat-vaio:~$ cd projects
   bolat@bolat-vaio:~/projects $ svn update; svn log

Sources,

   https://help.ubuntu.com/8.04/serverguide/C/subversion.html
   https://help.ubuntu.com/community/Subversion


Pratik Bilgiler

Comments (0)

Permalink

ARM7TDMI cross development with OpenOCD 0.5.0

In this article, I’ll talk about programming and debugging of ATMEL AT91SAM7S256 chips with OpenOCD 0.5.0.

This article covers cross compiling, cross debugging and OpenOCD configuration issues.

First of all, we need to install OpenOCD into our system.
I noticed that my development environment is Ubuntu 9.04 i386.

OpenOCD installation has 6 steps:
1- Installing dependencies,

   $ sudo apt-get install automake autoconf libftdi-dev flex build-essential libtool texinfo

2- Checking out OpenOCD from git repository,

   $ mkdir openocd0.5.0 && cd openocd0.5.0
   $ git clone git://openocd.git.sourceforge.net/gitroot/openocd/openocd
   $ cd openocd

3- Configuring OpenOCD,

   $ ./bootstrap
   $ ./configure --enable-ft2232_libftdi --enable-ep93xx --enable-rlink --enable-maintainer-mode

4- Compiling OpenOCD,

   $ make

5- Installing OpenOCD,

   $ sudo make install

6- Adding rules to udev in order to run OpenOCD as also normal user.
(If you do not add this script into udev, you cannot run openocd with usb jtag dongles, unless you are root!)
Create a 45-ft2232.rules file as root in /etc/udev/rules.d, and then copy and paste this script into it.

   BUS!="usb", ACTION!="add", SUBSYSTEM!=="usb_device", GOTO="kcontrol_rules_end"

   SYSFS{idProduct}=="0003", SYSFS{idVendor}=="15ba", MODE="664", GROUP="plugdev"

   LABEL="kcontrol_rules_end"

After adding this rule, do not forget the restart udev deamon.
In order to restart udev,

   $ sudo /etc/init.d/udev restart

This udev rule is specific for Olimex ARM-USB-OCD JTAG interface. if you would like to use another jtag dongle (rlink, amontec, etc), you have to change idPruduct and idVendor value of this configuration script with the jtag which you want to use.

Now, we can start OpenOCD
The simple way to start OpenOCD

   $ openocd -f configuration_file  <-s start_script> <-d#debug_verbosity_level>

‘<>‘ shows optional parameters.

   bolat@bolat-desktop:~/workspace/eclipse_sam7_blink_flash$ openocd -f at91sam7s256-armusbocd-flash-debug.cfg

starting openocd

Now, we can compile our sample project (from James P Lynch) and burn binary image into the ATMEL sam7s256 processor

   bolat@bolat-desktop:~/workspace/eclipse_sam7_blink_flash $ make all
   bolat@bolat-desktop:~/workspace/eclipse_sam7_blink_flash $ make program

Let us start to debug our code
In order to debug our code, we need to arm-linux-gdb; although in this project, i have used arm-elf-gcc, -so as to compile our source with debug symbols- arm-linux-gdb can be used without any problem.

    $ ddd --debugger arm-linux-gdb main.out

start ddd

as shown in the picture it is best way to start arm-linux-gdb in the working directory.

We have started ddd with arm-linux-gdb attached with main.out(elf file with debug symbols) but, it is not adequate to start debug process, to start debug process we should invoke gdb configuration script.
This can be 2 ways:
1- Prepare a configuration script and then execute in the gdb (in this case arm-linux-gdb) as shown in the picture

ddd debug configuration script

or
2- Prepare .gdbinit file in the working directory (where main.out is), then invoke gdb. In this case configuration script invoked immediately when the gdb runs.

Debugging application.
Debug script mentioned about in this article provides with four actions.
1- connection of the gdb server created by OpenOCD,

   target remote localhost:3333

2- Forces breakpoints as hardware breakpoints,

   monitor gdb_breakpoint_override hard

3- Loading debug symbols from file main.out,

   load

4- Last, setting up a hw breakpoint into main function entry.

   break main

It is almost done. Now you can debug our code with conventional gdb commands.
Incidentally, sam7p256 chips supports up to 2 hw breakpoints. If you cannot execute step and stepi command, decrease break points in use.

ddd debug

Project source code, openocd and arm-linux-gdb configuration scripts can be download here.

Good work

Bolat DINC

bolatdinc gmail com

Embedded Linux
Programming

Comments (2)

Permalink

DM355 EVM and DS1340 Realtime Clock

In this article i’ll talked about using DS1340 realtime clock on the DM355 EVM board.

TI DM355 EVM board has a rtc circuit that is formed by MSP430 uC but, it is not suitable for custom design especially cost restrictive applications. Therefore rtc circuit with DS1340 inserted into I2C bus on the evm board Data Connector (DC3). Details about i2c bus on the evm board can be obtain from TMS320DM355 Evaluation Module Technical Reference on page A-25

TI DM355 EVM

Fig:1 DM355 EVM Board

DM355 EVM board can be seen In fig 1.

In this application i have used linux kernel 2.6.31-rc7 on the DM355 evm board. Unfortunately kernel 2.6.10 and kernel 2.6.18 are maintained by MontaVista have no DS1340 RTC driver for Davinci DM355 platform. Be careful about ST M41T00 (DS1340 compliant) RTC is available on kernel 2.6.10 only for PowerPC (PPC32) architecture.

SM41T00 PPC Dependency

Our process has 4 steps:
1- Obtaining Kernel Source for linux-2.6.31-rc7.
2- Configuring kernel.
3- Editing dm355 board initialization file in the kernel.
4-Compiling the kernel.

1-Kernel source can be obtain:

   $ git clone  git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-davinci.git

2- In order to configure kernel:

   $ make ARCH=arm CROSS_COMPILE=arm_v5t_le- menuconfig

As can be seen on the picture DS1340 RTC module should be selected as static module.
DS1340 Configuration

3- And then you should edit linux-2.6.31-rc7/arch/arm/mach-davinci/board_dm355_evm.c DM355 EVM board initialization file:

$ gedit linux.2.6.31-rc7/arch/arm/mach-davinci/board-dm355-evm.c

edit dm355

then you can compile the kernel in the linux 2.6.31-rc7 kernel directory

   $ make ARCH=arm CROSS_COMPILE=arm_v5t_le- -j4 uImage

parameter at the last of make command is for spawn make process (it is useful for multi core/processor systems)

Kernel boot message after the implementation.

Starting again

Abort
DM355 EVM # tftp 0x80700000 uImage.2.6.31-rc7
TFTP from server 192.168.1.36; our IP address is 192.168.1.37
Filename 'uImage.2.6.31-rc7'.
Load address: 0x80700000
Loading: #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ##################
done
Bytes transferred = 1752812 (1abeec hex)
DM355 EVM # bootm 0x80700000
## Booting image at 80700000 ...
   Image Name:   Linux-2.6.31-rc7-davinci1-06212-
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    1752748 Bytes =  1.7 MB
   Load Address: 80008000
   Entry Point:  80008000
   Verifying Checksum ... OK
OK

Starting kernel ...

Uncompressing Linux............................................................................................................... done, booting the kernel.
Linux version 2.6.31-rc7-davinci1-06212-gdcfd73d-dirty (bolat@bolat-desktop) (gcc version 4.2.0 (MontaVista 4.2.0-16.0.32.0801914 2008-08-30)) #7 PREEMPT Fri Sep 4 14:12:30 EEST 2009
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
CPU: VIVT data cache, VIVT instruction cache
Machine: DaVinci DM355 EVM
Memory policy: ECC disabled, Data cache writeback
DaVinci dm355 variant 0x0
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 29464
Kernel command line: console=ttyS0,115200n8 noinitrd rw ip=192.168.1.37 root=/dev/nfs nfsroot=192.168.1.36:/home/bolat/embedded-linux/workdir/filesys,v3 mem=116M kgdboe=6443@192.168.1.37/,6442@192.168.1.36/
PID hash table entries: 512 (order: 9, 2048 bytes)
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
Memory: 116MB = 116MB total
Memory: 113976KB available (3084K code, 294K data, 116K init, 0K highmem)
SLUB: Genslabs=11, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
NR_IRQS:245
Console: colour dummy device 80x30
Calibrating delay loop... 107.72 BogoMIPS (lpj=538624)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
DaVinci: 104 gpio irqs
NET: Registered protocol family 16
MUX: initialized INT_EDMA_CC
MUX: Setting register INT_EDMA_CC
           INTMUX (0x00000018) = 0x00000000 -> 0x00000004
bio: create slab  at 0
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
musb_hdrc: version 6.0, pio, host, debug=0
musb_hdrc: USB Host mode controller at fec64000 using PIO, IRQ 12
musb_hdrc musb_hdrc: MUSB HDRC host driver
musb_hdrc musb_hdrc: new USB bus registered, assigned bus number 1
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 4096 (order: 3, 32768 bytes)
TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
TCP: Hash tables configured (established 4096 bind 4096)
TCP reno registered
NET: Registered protocol family 1
msgmni has been set to 222
io scheduler noop registered
io scheduler anticipatory registered (default)
Serial: 8250/16550 driver, 3 ports, IRQ sharing disabled
serial8250.0: ttyS0 at MMIO 0x1c20000 (irq = 40) is a 16550A
console [ttyS0] enabled
serial8250 serial8250.0: unable to register port at index 1 (IO0 MEM1c20400 IRQ41): -22
serial8250 serial8250.0: unable to register port at index 2 (IO0 MEM1e06000 IRQ14): -22
brd: module loaded
kgdb: Registered I/O driver kgdbts.
kgdbts:RUN plant and detach test
kgdbts:RUN sw breakpoint test
kgdbts:RUN bad memory access test
kgdbts:RUN singlestep test 1000 iterations
kgdbts:RUN singlestep [0/1000]
kgdbts:RUN singlestep [100/1000]
kgdbts:RUN singlestep [200/1000]
kgdbts:RUN singlestep [300/1000]
kgdbts:RUN singlestep [400/1000]
kgdbts:RUN singlestep [500/1000]
kgdbts:RUN singlestep [600/1000]
kgdbts:RUN singlestep [700/1000]
kgdbts:RUN singlestep [800/1000]
kgdbts:RUN singlestep [900/1000]
kgdbts:RUN do_fork for 100 breakpoints
dm9000 Ethernet Driver, V1.31
eth0: dm9000a at c7808000,c780c002 IRQ 65 MAC: 00:0e:99:02:c4:d4 (eeprom)
console [netcon0] enabled
netconsole: network logging started
116x: driver isp116x-hcd, 03 Nov 2005
sl811: driver sl811-hcd, 19 May 2005
r8a66597_hcd: driver r8a66597_hcd, 2009-05-26
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
usbcore: registered new interface driver ums-alauda
usbcore: registered new interface driver ums-cypress
usbcore: registered new interface driver ums-datafab
usbcore: registered new interface driver ums-freecom
usbcore: registered new interface driver ums-isd200
usbcore: registered new interface driver ums-jumpshot
usbcore: registered new interface driver ums-karma
usbcore: registered new interface driver ums-onetouch
usbcore: registered new interface driver ums-sddr09
usbcore: registered new interface driver ums-sddr55
usbcore: registered new interface driver ums-usbat
rtc-ds1307 1-0068: rtc core: registered ds1340 as rtc0
rtc-test rtc-test.0: rtc core: registered test as rtc1
rtc-test rtc-test.1: rtc core: registered test as rtc2
i2c /dev entries driver
watchdog watchdog: heartbeat 60 sec
TCP cubic registered
NET: Registered protocol family 17
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
Clocks: disable unused vpss_master
Clocks: disable unused vpss_slave
Clocks: disable unused mjcp
Clocks: disable unused uart1
Clocks: disable unused uart2
Clocks: disable unused asp0
Clocks: disable unused asp1
Clocks: disable unused mmcsd0
Clocks: disable unused mmcsd1
Clocks: disable unused spi0
Clocks: disable unused spi1
Clocks: disable unused spi2
Clocks: disable unused pwm0
Clocks: disable unused pwm1
Clocks: disable unused pwm2
Clocks: disable unused pwm3
Clocks: disable unused timer1
Clocks: disable unused timer3
Clocks: disable unused rto
rtc-ds1307 1-0068: setting system clock to 2009-09-09 09:39:05 UTC (1252489145)
eth0: link down
eth0: link up, 100Mbps, full-duplex, lpa 0x45E1
IP-Config: Guessing netmask 255.255.255.0
IP-Config: Complete:
     device=eth0, addr=192.168.1.37, mask=255.255.255.0, gw=255.255.255.255,
     host=192.168.1.37, domain=, nis-domain=(none),
     bootserver=255.255.255.255, rootserver=192.168.1.36, rootpath=
Looking up port of RPC 100003/3 on 192.168.1.36
Looking up port of RPC 100005/3 on 192.168.1.36
VFS: Mounted root (nfs filesystem) on device 0:14.
Freeing init memory: 116K
INIT: version 2.86 booting
Starting the hotplug events dispatcher: udevd.
Synthesizing the initial hotplug events...kgdb: Unregistered I/O driver kgdbts, debugger disabled.
done.
Waiting for /dev to be fully populated...done.
Activating swap...done.
Remounting root filesystem...done.
Calculating module dependencies
WARNING: Couldn't open directory /lib/modules/2.6.31-rc7-davinci1-06212-gdcfd73d-dirty: No such file or directory
FATAL: Could not open /lib/modules/2.6.31-rc7-davinci1-06212-gdcfd73d-dirty/modules.dep.temp for writing: No such file or directory
Loading modules:
Checking all file systems: fsck
fsck 1.40 (29-Jun-2007)
Mounting local filesystems: mount nothing was mounted
umount.nfs: /dev/root: not found or not mounted
Setting up networking ....
/etc/network/options is deprecated.
Setting up IP spoofing protection: rp_filter done.
Disabling IPv4 packet forwarding: done.
Disabling TCP/IP Explicit Congestion Notification: done.
Starting network interfaces: done.
Starting hotplug subsystem:
   pci
   pci      [success]
   usb
   usb      [success]
   isapnp
   isapnp   [success]
   ide
   ide      [success]
   input
   input    [success]
   scsi
   scsi     [success]
done.
Starting portmap daemon....
Cleaning: /tmp /var/lock /var/run done.
Setting pseudo-terminal access permissions...done.
Updating /etc/motd...done.
INIT: Entering runlevel: 3
Starting system log daemon: syslogd klogd.
Starting NFS common utilities: statd.
Starting internet superserver: inetd.
Starting OpenBSD Secure Shell server: sshd.

MontaVista(R) Linux(R) Professional Edition 5.0.0 (0801921)

192.168.1.37 login: root
Password:
Last login: Fri Sep  4 14:15:21 2009 on console
Linux 192.168.1.37 2.6.31-rc7-davinci1-06212-gdcfd73d-dirty #7 PREEMPT Fri Sep 4 14:12:30 EEST 2009 armv5tejl GNU/Linux

Welcome to MontaVista(R) Linux(R) Professional Edition 5.0.0 (0801921).

root@192.168.1.37:~#

Incidentally, in order to set RTC time and date

   # hwclock --set --date="09/09/2009 09:46:05"

Embedded Linux

Comments (0)

Permalink

gostericiler(pointer) ile birlikte const ve volatile kullanimi

Bu yazimda size embedded (gomulu) sistemelerde yaygin kullanimi olan volatile ve const belirleyicilerinden (specifiers) bahsedecegim.

Bilindigi uzere embedded sistemlerde giris/cikis (I/O) islemleri yogun bir sekilde ya aygit suruculeri uzerinden yada memory map sekilde gostericiler ile yapilmaktadir.

Farzedelim ki elinizde USART birimi olan bir 32 bit ARM7 islemcisi mevcut, ve USART birimi, kendisine uygun veri geldiginde 0×0000ABCD adresinde bulunan (rasgele verilmis bir deger) hafiza birimine -mikrodenetleyicinin dahili hafizasi- veriyi kopyalamaktadir. Boyle bir durumda compiler imizin optimizasyon islemi esnasinda azizligine ugramamak icin volatile belirleyicisi (specifier) kullanmamiz gerekir.

volatile belirleyicisi, derleme islemi esnasinda onunde bulundugu degiskenin optimizasyona tabi tutulupta sabit bir deger ile degistirilmesini engellemektedir.

Simdi kod uzerinden bunu gosterelim,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
.
.
volatile const unsigned * const p_stat = 0x0000ABCC; /*USART durum bilgisinin tutuldugu memory map address*/
 
volatile const unsigned * const p_data = 0x0000ABCD; /*USART dan okunan verinin tutuldugu memory map address*/
 
char data_to_read = 0;
 
char
usart_read(void);
 
void
main(void) {
   .
   .
   .
   for (;;) {
       .
       .
       .
       while(!(*p_stat & 0x0010));/*p_stat in gosterdigi veri alaninin 5'inci biti kontrol edilir*/
       data_to_read = usart_read ();
       .
       .
       .
   }
}
 
char
usart_read(void){
    return *p_data;
}

kod uzerinden de anlasilacagi uzere 4. ve 6. satirlarda volatile belirleyicisi kullanilmistir,
bu sayede 0×0000ABCC ve 0×0000ABCD degerlerinin p_stat ve p_data degiskenlerinde tutulacagi garanti altina alinmistir.

Simdi gelelim const belirleyicisine, 6. satirda dikkat edilirse iki defa const kelimesi kullanilmaktadir.

6
volatile const unsigned * const p_data = 0x0000ABCD;

bu ibareyi ingilizceye ardindanda turkceye cevirisek su mana cikacaktir.
p_data is a constant pointer that points to constant unsigned;
yani,
p_data sabit bir unsigned turunu gosteren sabit bir gostericidir.

Buradan ne anlamamiz gerekiyor. Aslinda burada const belirleyicisni kullanmasakta yazdigimiz program duzgun bir sekilde calisir, ancak uzerine veri yazilmasi istenmeyen sadece durum bilgisinin okunacagi bir bellek alaninin bu sekilde belirtilmesi ileride olusabilicek bug larin onune gecmek icin bir tedbir olacaktir.

Ozetlersek,

6
volatile const unsigned * const p_data = 0x0000ABCD;

ifadesi bize p_data nin optimizasyon esnasinda degerinin 0×0000ABCD sabitiyle degistirilmeyecegini ve gosterdigi bellek alaninin sadece bir peripheral (cevresel birim) tarafindan doldurulabilecegini anlatmaktadir.

Umarim faydasi dokunur
Iyi calismlar.

Programming

Comments (0)

Permalink

Servo motor nasil kontrol edilir?

Bu yazimda size R.C. Modellerde kullanilmakta olan servo motorlarin nasil calistigini ve nasil surulecegini anlatmaya calisacagim.

Servo motorlar torsiyonu yuksek, devirleri dusuk, hassasiyetleri yuksek mekanik kontrol elemanlaridir.

Simdi gelelim bu motorlarin ozelliklerine.

Bu tip sistemler besleme terminallerine gerekli voltaj degeri verilir verilmez calismazlar. Calismlari icin ayrica besleme terminalleri disinda yer alan kontrol terminaline de PWM isaret yollamaniz gerekir.
PWM nin ne oldugunu burada anlatmayacagim internette zaten bu konuda istemediginiz kadar kaynak mevcut ancak burada onemli olan husus, PWM sinyalinin duty-cycle (darbe suresi/sinyal periyodu) nin servo konumunu degistirdigi, sinyal periyodunun da servo motorun calisma hizini degistirdigidir. PWM periyodu azaldikca servo daha hizli tepki verecek anacak bir o kadarda kararsiz olacaktir.


not: bu resim http://www.digitalnemesis.com/info/docs/rcservo/ adresinden alinmistir

Sekildende anlasilacagi uzere besleme terminalleri disindaki terminale kontrol icin gerekli PWM sinyanli uygulanmaktadir.

Simdi gelelim gerekli duzenegin devre semasina.

Devre PWM sinyalini uretmek icin bir mikrodenetleyici ve bir servo motordan olusmaktadir.
uC ni calismasi icin ayrica 4Mhz lik kristal (HS) rezonator baglanmistir. 13-14 numarali pinler.
uC nin TX ve RX pinleride TTL - RS232 cevrimi icin max232 ye baglanmistir.
Onemli not: Kullandiginiz rezonatorun uretmis oldugu sinyalin faz gurultusunun azaltmak icin 22pf lik kondansoterleri yuk olarak baglamayi unutmayin.

Servo Motor Kotrol

Devre semasindan da gorlecegi uzere uC nin RE0 pini Servo motorun kontrol terminaline baglanmistir.

Uygulamanin HI-TECH PICC’ de yazilmis programi:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <pic.h>
#include <htc.h>
#include "delay.h"
#include "usart.h"
 
// Setup the configuration word for ise with ICD2
__CONFIG(HS & DEBUGEN & WDTEN & LVPDIS);
/*
 *	Interrupt demo for PIC; wait for button press on RB0/INT,
 *	turn on a relay on another port bit for a period of time.
 *	For simplicity here, literal constants are used, usually these
 *	should be calculated with compile-time arithmetic.
 */
 
bit bit_timer_first  = 0;
bit bit_timer_second = 0;
 
unsigned char uc_delay = 0;
 
void
main(void){
	TRISE &= 0b11111110;/*RE0 cikis olarak ayarli*/
	OPTION = 0b00000111;/*TMR0 ayarla PS:256*/
	RBPU   = 0; 
	T0IE   = 1;   /*TMR0 interrupti acik*/
	INTEDG = 1; 
	INTE = 1;   
	RCIE = 1;  /*Seri port alma interrupti acik*/
	TXIE = 1;  /*Seri port gonderme interrupti acik*/
	GIE  = 1; /*butun interruplar acik*/
 
	init_comms(); /*uarti baslat*/
 
	for(;;){
		if ( bit_timer_first ) { /*her PWM sinyali periyonu boyunca calis*/
			RE0 = 1;
			DelayUs(250);
			DelayUs(250);
			DelayUs(uc_delay);
			DelayUs(uc_delay);
			DelayUs(uc_delay);
			DelayUs(uc_delay);
			RE0 = 0;
			bit_timer_first = 0;
			CLRWDT();
		}	
		CLRWDT();
	}
}
 
static void 
interrupt isr(void){// Here be interrupt function - the name is unimportant.
	if(T0IF) {  // timer interrupt
		bit_timer_first = 1;
		TMR0 = 177;  /*freq = (FOSC/4)/(Prescaler*(255-TMR0))*/
		T0IF = 0;    // clear the interrupt flag
	}
 
	if(INTF) {    // did we see a button press?
		/*NULL*/
		INTF = 0;    // clear the interrupt
	}
 
	if(RCIF){
		uc_delay = RCREG;
		RCIF=0;
	}
 
	if(TXIF){
		/*NULL*/
		TXIF = 0;
	}
}

Program kodundan da anlasilacagi uzere 9600 8 N 1 seklinde gelen seriport verisi interrupt sekline ‘uc_delay’ degerini guncellemektedir. ‘uc_delay’ degeride PWM icin gerekli darbe suresini belirleyecek sekilde gecikme saglamaktadir. Bu programda uC in TMR0 birimi PWM sinyali icin gerekli periyodik gecikmeyi saglamak amaciyla frekansi (1/PWM periodu) ~50Hz olacak sekilde kurulmustur.

Simdi de uygulamanin resmine bakalim….

Servo Motor Kotrol

Umarim faidesi olmustur.

Iyi calismalar dilerim.

Pratik Bilgiler

Comments (2)

Permalink

Pronghorn SBC-250 ve Strataflash uzerine bootloader yazimi

Merhaba,
Bu yazimda size ADI Engineering’ in Pronghorn SBC-250 kartlarinda Bootloader in nasil yazilacagini anlatmaya calisacagim.
ADI Engineering in uretmis oldugu Pronghorn SBC-250 kartlarinda Linux 2.6.17 kerneli on yuklu olarak gelmektedir.
Sistem acildiktan sonra strata flash uzerindeki partitionlar (MTD, memory technology device) /dev klasoru icerisinde bulunmaktadir. Yanlis hatirlamiyorsam,

/dev/mtdblock0
/dev/mtdblock1
.
.
.
/dev/mtdblock4

Seklinde olmasi gerekiyor.

Sayet olurya boyle bir hatayi yapacaginizi hic dusunmuyorum ama ginede olduya siz fantazi olsun diye

root@pronghorn-sbc ~ # mount /dev/mtdblock0 /mnt

dediniz ve /mnt klasorunun icine birseyler kopyaladiniz hatta bu klasorun icini tamamen sildiniz.
Gecmis olsun /dev/mtdblock0 icerisinde bulunan Bootloader (RedBoot) ununz uctu ve birdaha SBC nin acilmayacak.
Panige gerek yok binlerce euro para verip sadece XScale firmware i yuklu bir OCD almaniza gerek yok SBC nizin
yeniden acilir hale gelmesi icin.
Pronghorn SBC 250 - Openocd
Simdi bu islemi nasil yapacaksiniz
1-Oncelikle OpenOCD yi sistemimize kuruyoruz.

   	$ svn checkout -r 658 svn://svn.berlios.de/openocd/trunk
	$ cd trunk
	$ ./bootstrap
	$ ./configure --enable-ft2232_libftdi
	$ make
	$ sudo make install

2-Ardindan sekilde gorulen OpenOCD uyumlu JTAG imizi kartimiza bagliyoruz. Baglantida karmasik bir durum yok sadece bire bir baglanti.

3- JTAG imizi bilgisayara bagladiktan sonra asagidaki konfigurasyon dosyasi ve init scripti ile birlikte

       $ sudo openocd -f openocd.cfg -d

diyerek openocdmizi calistiriyoruz.
Artik,

       $ telnet localhost 4444

diyerek Openocdmiz ile strataflash in uzerine veri yazabiliriz.
Konu ile alakali resim ve belgeleri buradan indirebilirsiniz.

Iyi calismalar.

Embedded Linux

Comments (0)

Permalink

Bir is mulakatinda basiniza gelebilecekler 2

Mulakata girdigim Meshur firmada sorulan sorulardan biride, herbir nodu

1
2
3
4
5
6
struct list_s {
    char *name;
    char *surname;
    unsigned index;
    struct list_s *next;
};

seklinde olan bir linked list in icerisindeki butun elemanlari ile nasil kopyalanacagiydi.
(bu islemei yapan bir C fonksiyonu yazilacak)

Asgidaki kodda uygulamasini gorebilirsiniz.
Uygulamanin kaynak kodunu buradan indirebilirsiniz.

hede@hodo ~ $ gcc -o llist llist.c

seklinde derleyeyin

hede@hodo ~ $ ./llist

ile calistirin

Yazilim firmalarinda mulakada gireceklere basarilar.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/*
Bolat Dinc Linked List example.
31.03.2009
bolatdinc-{at}-gmail.com
for more information look at http://en.wikipedia.org/wiki/Linked_List
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
struct list_s {
    char    *name;
    char    *surname;
    unsigned index;
    struct list_s *next;
};
 
/*
*
-------------------------------Prothotype Declerations--------------------------
*
*/
 
struct list_s*
list_s_add_front(struct list_s **p, char *name, char *surname);
 
struct list_s*
list_s_copy(struct list_s **new_list, struct list_s **source_list);
 
struct list_s*
list_copy_node(struct list_s **new_node, struct list_s **source_node);
 
void
list_print(struct list_s *n);
 
void
list_remove(struct list_s **p);
 
int
main(int argc, char **argv){
    struct list_s *list_deneme = NULL;
    struct list_s *list_copy   = NULL;
 
    list_s_add_front(&list_deneme, "Fonksiyon", "Pointeri");
    list_s_add_front(&list_deneme, "Implicit", "Cast");
    list_s_add_front(&list_deneme, "Posix", "4.3");
    list_s_add_front(&list_deneme, "Select", "Poll");
    list_s_add_front(&list_deneme, "Volatile", "Constant");
    list_s_add_front(&list_deneme, "Bitwise", "AndOr");
 
    list_s_copy(&list_copy ,&list_deneme);
 
    printf("\n----list_deneme-----\n");
    list_print(list_deneme);
    printf("\n----list_copy-----\n");
    list_print(list_copy);
 
    list_remove(&list_deneme);
    list_remove(&list_deneme);
    list_remove(&list_deneme);
    list_remove(&list_deneme);
    list_remove(&list_deneme);
    list_remove(&list_deneme);
    list_remove(&list_copy);
    list_remove(&list_copy);
    list_remove(&list_copy);
    list_remove(&list_copy);
    list_remove(&list_copy);
    list_remove(&list_copy);
 
    printf("\n----list_deneme-----\n");
    list_print(list_deneme);
    printf("\n----list_copy-----\n");
    list_print(list_copy);
 
    return 0;
}
 
/*
Function name    : struct list_s* list_s_add_front(struct list_s **p, char *name, char *surname);
Parameters       : struct list_s **p  -> A pointer of the linked list;
                   char *name -> A pointer of the name field of the node
                   char *surnaname -> A pointer of the surname field of the node
Return Value     : A pointer of the linked list that heve been created.
Description	 : This function creates a linked list by adding nodes at the front
                   of the linked list.
*/
struct list_s*
list_s_add_front(struct list_s **p, char *name, char *surname){
    char *fname = "list_s_add_front()";
    /*Create new node at the front of the linked list*/
    struct list_s * n = (struct list_s*) malloc(sizeof(struct list_s));
    if(n == NULL){
        printf("Memory allocation error in %s line: %d\n", fname , __LINE__-2);
        exit(-1);
    }
    n->next = *p;
    *p = n;
    /*Rezerve memory location for 'name' field*/
    n->name = (char*) malloc(strlen(name)+1);
    if(n->name == NULL){
        printf("Memory allocation error in %s line: %d\n", fname , __LINE__-2);
        exit(-1);
    }
 
    /*Rezerve memory location for 'surname' field*/
    n->surname = (char*) malloc(strlen(surname)+1);
    if(n->surname == NULL){
        printf("Memory allocation error in %s line: %d\n", fname , __LINE__-2);
        exit(-1);
    }
 
    strcpy(n->name, name);
    strcpy(n->surname ,surname);
    return *p;
}
 
/*
Function name    : struct list_s* list_s_copy(struct list_s **s1, struct list_s **s2);
Parameters	      : struct list_s **s1 -> A pointer of the linked list which points the copy of the linked list.
                   struct list_s **s2 -> A pointer of the linked list which will be copied.
Return Value     : A pointer of the linked list which points the copy of the linked list.
Description	     : This function creates a linked list that entirely copy of 'source_list'.
*/
struct list_s*
list_s_copy(struct list_s **new_list, struct list_s **source_list){
    /*
    char *fname  = "list_s_copy()";
    */
    struct list_s *tmp_new_list 	= NULL;
    struct list_s *tmp_source_list	= *source_list;
 
    if (tmp_source_list == NULL){
        *new_list = *source_list;
        return *new_list;
    }
 
    for(;tmp_source_list!=NULL;) {
        /*define head pointer of the copied linked list*/
        if (*new_list == NULL){
            list_copy_node(new_list, source_list);
            /*reserve head pointer of the copied linked list*/
           tmp_new_list = *new_list;
        } else {
            list_copy_node(&(tmp_new_list->next), &(tmp_source_list->next));
            tmp_new_list = tmp_new_list->next;
            tmp_source_list = tmp_source_list->next;
        }
    }
    return *new_list;
}
 
/*
Function name    : struct list_s* list_copy_node(struct list_s **s1, struct list_s **s2);
Parameters	      : struct list_s **s1 -> A pointer of copied node.
                    struct list_s **s2 -> A pointer of node which will be copied.
Return Value     : A pointer of copied node.
Description	     : This function creates a node then copies the source node into new node.
*/
struct list_s*
list_copy_node(struct list_s **new_node, struct list_s **source_node){
    char *fname = "list_copy_node()";
    if (*source_node==NULL){
        *new_node = NULL;
        return NULL;
    }else{
        *new_node = (struct list_s*) malloc(sizeof(struct list_s));
        if(*new_node == NULL){
            printf("Memory allocation error in %s line: %d\n", fname, __LINE__-2);
            exit(-1);
        }
 
        (*new_node)->name = (char*) malloc(strlen((*source_node)->name)+1);
        if((*new_node)->name == NULL){
            printf("Memory allocation error in %s line: %d\n", fname , __LINE__-2);
            exit(-1);
        }
 
        (*new_node)->surname = (char*) malloc(strlen((*source_node)->surname)+1);
        if((*new_node)->surname == NULL){
            printf("Memory allocation error in %s line: %d\n", fname , __LINE__-2);
            exit(-1);
        }
 
        strcpy((*new_node)->name, (*source_node)->name);
        strcpy((*new_node)->surname, (*source_node)->surname);
        (*new_node)->next = NULL;
        return *new_node;
    }
}
 
/*
Function name    : void list_print(struct list_s *n);
Parameters	   : struct list_s *n -> A pointer of the linked list to be printed from head to taill.
Return Value   : void
Description	 : Prints the linked list which passed from input parameter.
*/
void
list_print(struct list_s *llist){
    if (llist == NULL) {
        printf("list is empty\n");
    }
    while (llist != NULL){
        printf("print %p %p %s %s\n", llist, llist->next, llist->name, llist->surname);;
        llist = llist->next;
    }
}
 
/*
Function name    : void list_remove(struct list_s **p);
Parameters	    : struct list_s **p -> A pointer of the linked list to be removed its head node.
Return Value  : void
Description	  : Removes head node of the linked list which passed from parameter.
*/
void
list_remove(struct list_s **llist_head){
    if (*llist_head != NULL)	{
        struct list_s *n = *llist_head;
        *llist_head = (*llist_head)->next;
        free(n);
    }
}

General

Comments (0)

Permalink

Bir is mulaktinda basiniza gelebilecekler…

Merhaba,
Bu makalede size unlu bir gomulu yazilim firmasinda maruz kaldigim birkac garip soruyu ve bunlarin yorumunu paylasmak istiyorum.

Maruz kaldigim mulakatta:

1
2
3
4
5
6
7
8
9
10
11
12
/*module ise_almiyacagiz.c begin*/
#include <stdio.h>
 
int
main(){
   char array[] = {'s', 'e', 'n', 'i', ' ', 'i', 's', 'e', '  ', 'a', 'l', 'm', 'i', 'y', 'a', 'c', 'a', 'g', 'i', 'z', '!'};
   char *p;
   p = &array+1; /*Trap*/
   printf("character = %c\n", *(p-1));
   return 0;
}
/*module ise_almiyacagiz.c end*/

seklinde bir soru vardi.

Bu soruda istenen ekrana neden ‘!’ isaretinin basildigi idi.
Evet sasirmayin, bu kodu gcc,

p = &array+1;

satirinda bir yamukluk var uyarisi ile derleyip elf dosyasini olusturabiliyor.
Ve ekran ciktisida (derleme islemi ile birlikte):

hede@hodo ~$gcc -o ise_almiyacagiz ise_almiyacagiz.c
hede@hodo ~$./ise_almiyacagiz
!
hede@hodo ~$

seklinde.

Sanirim size de garip geldi

p = &array+1;

burada bir pointerin adresini neden bir sayi ile toplaniyor; aritmetik islem desem degil, pointer aritmetigi desem pointerin basinda & isaretinin ne isi var diye.

Burada puf nokta soyleymis:

p = &array+1;

yapildiginda array olarak gosterilen pointerinin gosterdigi bellek alaninin uzunlugu kadar bir oteleme saglaniyormus. Boyle oluncada *(p-1) dizinin son elemanini gosteriyor tabiki.

Simdi de uygulamayi ddd uzerinden debug edelim.

DDD debug

DDD debug

Debug islemindende anlasilacagi uzere ‘&array’ in degeri (char (*)[21]) seklinde.
Simdi bu satiri,

8
p = &array+1;

su sekilde yazabiliriz

8
p = array+sizeof(char(*)[21])*1;

programlamada cok sik karsilasmayabileceginiz problemler icin basarilar dilerim.

Yazilim firmalarinda mulakata gireceklere basarilar….

General

Comments (0)

Permalink

scp çalışmadığında…

EDB9302 uyumlu ve uzerinde root file sistem olarak BuildRoot kullandigim gomulu kartimda openssh hatasiz bir sekilde derlemistim.
Olusan root file sistemimde ssh deamonu calismasina ragmen scp komutunu kullanamamaktaydim.

edb9302@arm-linux~$scp bolatd@192.168.1.4:/home/bolatd/deneme.tar /home/edb9302

seklinde bir komut calistirdigimda, “OpenSSH Segmentation Fault”, hatasi vermekteydi.
Bu hatanin etrafindan dolasmak için asagidaki degisikligi yaparak tekrar dosya kopyalamayi denedim.

edb9302@arm-linux ~$ ssh -l bolatd 192.168.1.4 tar -c /home/bolatd/deneme.tar | (cd /home/edb9302; tar -x)

bu sekilde embedded sistemimin icinden bir dosyayi uzak bir makineden kopyalayabildim.
Umarim sizede faydasi dokunur.

Pratik Bilgiler

Comments (0)

Permalink