Lock free atomic operations

I would like to share another interview question in this article.

x as a global variable, provide these operations x++; x%=20; atomically without using locks.

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
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <pthread.h>
#include <sys/types.h>
 
#define THREAD_NUM 9
#define INC_NUM 32767
 
#define ATOMIC
//#define NON_ATOMIC
//#define MUTEX_LOCK /*this is for verification*/
 
volatile int x = 0;
 
 
void *thread_func(void *ptr);
#ifdef MUTEX_LOCK
pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
 
int main(int argc, char **argv) {
    pthread_t thread[THREAD_NUM];
    int iret[THREAD_NUM];
    int nt;
    for (nt = 0; nt<THREAD_NUM; nt++) {
	if ((iret[nt] = pthread_create( &thread[nt], NULL, thread_func, (void *)nt))) {
             fprintf(stderr, "Thread creation error!\n");
             return EXIT_FAILURE;
        }
    }
 
    for (nt = 0; nt<THREAD_NUM; nt++)
        pthread_join(thread[nt], NULL);
 
    printf("counter val = %d\n", x);
    return 0;
}
 
void *thread_func(void *ptr) {
    int cnt;
#ifdef ATOMIC
    __typeof__(x) tempx;
#endif
    printf("Thread %lu started.\n", (unsigned long)ptr);
    for (cnt = 0; cnt<INC_NUM; cnt++) {
#ifdef ATOMIC
	do{
	   tempx = x;
	}while (!__sync_bool_compare_and_swap(&x, tempx, (tempx+1)%20));
#endif
#ifdef NON_ATOMIC
	x++;
	x %= 20;
#endif
#ifdef MUTEX_LOCK
         pthread_mutex_lock(&thread_mutex);
         x++;
	 x %= 20;
         pthread_mutex_unlock(&thread_mutex);
#endif
    }
    printf("Thread %lu finished.\n", (unsigned long)ptr);
    return NULL;
}

Good luck for the interviews!

Programming

Comments (0)

Permalink

Dalvik Virtual Machine on TS-7800 SBC

Hey There,

In this article, I am going to talk about how to port Dalvik Virtual Machine on TS-7800 embedded board. Also in the article, you may find basic procedures to build Android OS from scratch.

Basic setup of the SBC can be seen from Figure.1. In brief, if we need to talk about the SBC, we can say the board has 88F5182 XScale ARM processor, 128 MB SDRAM and GPIOs, you may find more on the official web site of the product. Incidentally, I was about to forget, I used kernel 2.6.34 on this embedded board. Unfortunately the firmware image which is shipped with the product provides kernel 2.6.21-ts, and it is not convenient to port ashmem device (which is specific to Android Kernel) on this kernel version. You should download the latest firmware.

An XScale single board computer

                  Figure.1: TS-7800 Single Board Computer with XScale ARM proccessor.

Dalvik Virtual Machine is the main component of Google Android OS, so if we want to port Android OS on a new platform, first we need to port Dalvik Virtual Machine on it.

So, let’s build Android Operating System, by the way I am not going to talk about detailed build procedures, you may find these steps from official Google Android web site.

$ mkdir ~/bin
$ PATH=~/bin:$PATH

$ curl https://android.git.kernel.org/repo > ~/bin/repo
$ chmod a+x ~/bin/repo

$ mkdir ~/android
$ cd ~/android

$ repo init -u git://android.git.kernel.org/platform/manifest.git
$ repo init -u git://android.git.kernel.org/platform/manifest.git -b froyo

$ repo sync

$ export TARGET_ARCH=arm
$ export TARGET_ARCH_VERSION=armv5tej
$ export TARGET_CPU_ENDIAN=EL
$ export USE_CCACHE=1
$ source build/envsetup.sh
$ choosecombo
Build for the simulator or the device?
     1. Device
     2. Simulator

Which would you like? [1] 1

Build type choices are:
     1. release
     2. debug

Which would you like? [1] 2

Which product would you like? [generic] generic

Variant choices are:
     1. user
     2. userdebug
     3. eng
Which would you like? [eng] 3

============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=2.2.1
TARGET_PRODUCT=generic
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=false
TARGET_BUILD_TYPE=debug
TARGET_BUILD_APPS=
TARGET_ARCH=arm
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=MASTER
============================================

$ make -j4 PRODUCT-generic-eng

Last operation will take an our or more depending on your cpu processing speed. After the compilation we need to copy Android Binaries into target root file system.

$ cp -a ~/android/out/debug/target/product/generic/system /dev/rfs

In this setup, I used the SD flash memory as the root file system drive, and it is mounted on /dev/rfs on my PC in order to copy Android Binaries.

Until here, operations are simple procedures, and easy to find from Google Android web site. But the problem is, there are not clear procedures to make Dalvik Virtual Machine up and running on a new platform. This is too important, android operating system does not use SysV shared memory methods in order to achieve IPC, therefore, you have to implement Android Shared Memory -/dev/ashmem- device on your system.

       Figure.2: Dalvik Virtual Machine Kernel Dependencies.

These are the steps to port ashmem device on kernel 2.6.34,

1- $ cp ashmem.c linux-2.6.34/mm
   $ cp ashmem.h linux-2.6.34/include/linux/

2- Open linux-2.6.34/mm/Kconfig file, and add these lines on the bottom of the file,

config ASHMEM_MODULE
	tristate "asmem module"
	depends on ARM
	default m if ARM
	help
		Android ashmem module. Provides specific shared memeory interface
		to DalvikVM.

3- Open linux-2.6.34/mm/Makefile, and add this line on the bottom of the file,

obj-$(CONFIG_ASHMEM_MODULE) += ashmem.o

There are also two important issues to port ashmem.c,

You should add the extra C codes below,

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/*B.D. begin*/
#include <linux/ashmem.h>
#include <linux/swap.h>
 
static LIST_HEAD(shrinker_list);
static DECLARE_RWSEM(shrinker_rwsem);
 
/*http://android.git.kernel.org/?p=kernel/common.git;a=blob;f=mm/memory.c*/
static const struct vm_operations_struct shmem_vm_ops;
static void shmem_set_file(struct vm_area_struct *vma, struct file *file) 
{
	if (vma->vm_file) 
		fput(vma->vm_file); 
	vma->vm_file = file; 
	vma->vm_ops = &shmem_vm_ops; 
} 
/*B.D. end*/

and make sure register_shrinker, unregister_shrinker kernel API’s defined as

EXPORT_SYMBOL(register_shrinker);
EXPORT_SYMBOL(unregister_shrinker);

to allow dynamic linking.

For now, we are good to go, and we need to compile the kernel, but I am not going to talk about kernel compilation. You may find the details from here.

After compilation of the kernel, we need to copy asmem.ko file into the root file system under
/lib/modules/2.6.34/kernel/android.
Now we are done, we can load the ashmem device by typing,

   $ insmod /lib/modules/2.6.34/kernel/android/ashmem.ko

OK, let’s verify Dalvik,

You may use the sample java code below to run on Dalvik Virtual Machine,

1
2
3
4
5
6
7
8
9
10
11
class Foo { 
	public static void main(String[] args) {
          for(int i = 1; i<100; i++){
		  try {
			System.out.println("DalvikVM on ts-7800! : " + i);
			Thread.sleep(250);
		  } catch (InterruptedException x) {
		  }
          }
	} 
}

In order to convert class file into Dalvik Executable (dx), you should install Android SDK on your development machine(in my case Ubuntu 11.04-i386).

$ javac Foo.java
$ dx --dex --output=foo.jar Foo.class

Now , We can test our sample dx application!

First we need to prepare a sample bash script to prepare environment variables for Dalvik Virtual Machine execution on the SBC,

1
2
3
4
5
6
7
8
9
10
#!/bin/bash
 
export ANDROID_ROOT=/system
export BOOTCLASSPATH=/system/framework/core.jar:\
/system/framework/ext.jar:/system/framework/framework.jar:\
/system/framework/android.policy.jar:/system/framework/services.jar
 
export ANDROID_DATA=/tmp/dalvik_$USER
mkdir -p $ANDROID_DATA/dalvik-cache
exec dalvikvm $@

then we need to copy dx file (foo.jar) into the embedded system,

Now, we can run dalvikvm,

Dalvik Virtual Machine Execution

I hope, it will work for you applications.

Any kinds of feedback are welcome!

Embedded Linux
GNU/Linux
Linux Device Drivers

Comments (0)

Permalink

3 interview questions in 28 minutes

Hi,

I would like to share 3 interview questions which have been asked me during a job Interview.

1- Write a function which omits space characters and concatenates every word in a one string.
ex: “ABCD EF -GHI<" -> “ABCDEF-GHI<"

2- Write a function which calculates 1 digits in a uint8t variable.
ex: 0xAA -> 4

3- Write a function which detects a linked list is singly circulated.

Here is the answers,

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
#include <stdio.h>
 
typedef unsigned char uint8_t;
 
struct linked_list {
	int data;
	struct linked_list *next;
};
 
char string[] = "ABC DEF  -GHI    JKLM<";
uint8_t gdata = 0x55;
 
/*
*1- Write a function which omits space characters and concatenates every word in a one string.
*/
void omit_space(char *ptr) {
 int shift = 0;
 while (1) {
  switch (*ptr) {
   case (' ') : shift++; break;
   case ('\0'):	*(ptr-shift) = *ptr; return;
   default : if (shift) *(ptr-shift) = *ptr;
  }
  ptr++;
 }
}
 
/*
*2- Write a function which calculates 1 digits in a uint8t variable.
*/
uint8_t count_set_bits(uint8_t data) {
 uint8_t counter = 0;
 while (data) {
   if (data & 1) {
    counter++;
   }
   data>>=1;
  }
 return counter;
}
 
/*
*3- Write a function which detects a linked list is singly circulated.(*)
*/
int islistCircular(struct linked_list *head) {
 struct linked_list *ptr_slow   = head;
 struct linked_list *ptr_fast	= head;
 
 while (1) {
   if (ptr_slow && ptr_fast && ptr_fast->next) {
	ptr_slow = ptr_slow->next;
	ptr_fast = ptr_fast->next->next;
   } else {
	return 0;
   }
   if (ptr_slow == ptr_fast) {
      return 1;
   }
  }
}
 
int
main(int argc, char **argv) {
  printf("\n%s\n", string);
  omit_space(string);
  printf("\n%s\n", string);
  printf("\nbit numbers '1' in 0x%x is %d\n", gdata, count_set_bits(gdata));
  return 0;
}

* : you may read more detailed answer for this question from Expert C Programming, Peter Van Linden, Page 334, ISBN: 0-13-177429-8.

See you on another article…

General

Comments (0)

Permalink

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 (4)

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.

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 real-time 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

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 (5)

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 biri de, 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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/*
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;
        int i;
	for (i = 0; i<1000; i++) { /*iterative test to detect memory leak! */
		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 = NULL;
		return NULL;
	}
 
	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->name); /*delete dynamic node fields*/
		free(n->surname);
		free(n); /*delete node*/
	}
}

General

Comments (0)

Permalink