tcl言語とC言語の連携
tcl言語でC言語の関数を使う
tcl言語はプラットフォームを問わず幅広く使われている言語です。今回は、
tcl言語は高水準のインタープリタなので、
ここではC言語で簡単な演算を行う関数を作成し、
tcl言語から呼び出すC言語関数
全ての引数の数と累積加算の戻り値を返すC言語側の関数は、
tcl言語から呼び出されるC言語で書かれた自作共有ライブラリ内での関数の戻り値は、
初期化関数名は以下となります。
int [任意の名称]_Init(Tcl_Interp *interp)
任意の名称は必ずしも共有ライブラリ名と一致させる必要はなく、
tcl言語から呼び出されるC言語の関数の仕様は、
01: #include <tcl.h>
02:
03: int CalcCmd(ClientData clientdata, Tcl_Interp *interp, int argc, char **argv);
04:
05: int Calc_Init(Tcl_Interp *interp) {
06: Tcl_CreateCommand(interp, "calc", CalcCmd, (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
07: Tcl_PkgProvide(interp, "calc", "1.1");
08: return TCL_OK;
09: }
10:
11: int CalcCmd(ClientData clientdata, Tcl_Interp *interp, int argc, char **argv) {
12: int data, i, n, error;
13:
14: if(argc <= 2) {
15: interp->result = "Usage: calc num num ...";
16: return TCL_ERROR;
17: }
18: data = 0;
19: for(i = 1;i < argc;i++) {
20: error = Tcl_GetInt(interp, argv[i], &n);
21: if(error != TCL_OK) return error;
22: data += n;
23: }
24: sprintf(interp->result, "%d", data);
25: return TCL_OK;
26: }
tcl言語から呼び出されるC言語の関数を記述する場合は、
また、
自作共有ライブラリ内での初期化関数やtcl言語から呼び出されるC言語の関数とtcl言語インタープリタ処理系とのインターフェースは、
初期化関数においては、
tcl言語から呼び出されるC言語の関数の生成は、
tcl言語から呼び出されるC言語の関数の登録は、
tcl言語から呼び出されるC言語の関数であるCalcCmd関数
tcl言語から呼び出されるC言語の関数内で数値などの引数の実体を取得するには、
C言語での戻り値は TCL_
Lua言語からのハードウェアアクセス
C言語での記述
前回、
001: #include <sys/types.h>
002: #include <sys/stat.h>
003: #include <fcntl.h>
004: #include <unistd.h>
005: #include <stdlib.h>
006: #include <stdio.h>
007: #include <string.h>
008: #include <sys/mman.h>
009: #include <asm/page.h>
010:
011: #include <lua.h>
012: #include <lualib.h>
013: #include <lauxlib.h>
014:
015: static void MemoryByteWrite(lua_State *List, unsigned int addr, unsigned int data);
016: static unsigned int MemoryByteRead(lua_State *List, unsigned int addr);
017: static void MemoryWordWrite(lua_State *List, unsigned int addr, unsigned int data);
018: static unsigned int MemoryWordRead(lua_State *List, unsigned int addr);
019: static void MemoryLongWrite(lua_State *List, unsigned int addr, unsigned int data);
020: static unsigned int MemoryLongRead(lua_State *List, unsigned int addr);
021:
022: static void MemoryByteWrite(lua_State *List, unsigned int addr, unsigned int data) {
023: volatile unsigned char *mmaped;
024: int fd, i;
025: unsigned int pageaddr, offsetmask, pagemask;
026:
027: fd = open("/dev/mem",O_RDWR);
028: if(fd < 0) {
029: lua_pushstring(List, "Cannot open /dev/mem");
030: lua_error(List);
031: }
032: offsetmask = PAGE_SIZE;
033: offsetmask--;
034: pagemask = ~offsetmask;
035: pageaddr = addr & pagemask;
036: mmaped = (volatile unsigned char*)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, pageaddr);
037: close(fd);
038: if(mmaped == MAP_FAILED) {
039: lua_pushstring(List, "Cannot mmap");
040: lua_error(List);
041: }
042: mmaped[addr & offsetmask] = data;
043: munmap((char*)mmaped, PAGE_SIZE);
044: }
045:
046: static unsigned int MemoryByteRead(lua_State *List, unsigned int addr) {
047: volatile unsigned char *mmaped;
048: int fd, i;
049: unsigned int pageaddr, offsetmask, pagemask, data;
050:
051: fd = open("/dev/mem",O_RDWR);
052: if(fd < 0) {
053: lua_pushstring(List, "Cannot open /dev/mem");
054: lua_error(List);
055: }
056: offsetmask = PAGE_SIZE;
057: offsetmask--;
058: pagemask = ~offsetmask;
059: pageaddr = addr & pagemask;
060: mmaped = (volatile unsigned char*)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, pageaddr);
061: close(fd);
062: if(mmaped == MAP_FAILED) {
063: lua_pushstring(List, "Cannot mmap");
064: lua_error(List);
065: }
066: data = mmaped[addr & offsetmask] & 0xff;
067: munmap((char*)mmaped, PAGE_SIZE);
068: return data;
069: }
070:
071: static void MemoryWordWrite(lua_State *List, unsigned int addr, unsigned int data) {
072: volatile unsigned short *mmaped;
073: int fd, i;
074: unsigned int pageaddr, offsetmask, pagemask;
075:
076: fd = open("/dev/mem",O_RDWR);
077: if(fd < 0) {
078: lua_pushstring(List, "Cannot open /dev/mem");
079: lua_error(List);
080: }
081: offsetmask = PAGE_SIZE;
082: offsetmask--;
083: pagemask = ~offsetmask;
084: pageaddr = addr & pagemask;
085: mmaped = (volatile unsigned short *)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, pageaddr);
086: close(fd);
087: if(mmaped == MAP_FAILED) {
088: lua_pushstring(List, "Cannot mmap");
089: lua_error(List);
090: }
091: mmaped[(addr & offsetmask) >> 1] = data;
092: munmap((char*)mmaped, PAGE_SIZE);
093: }
094:
095: static unsigned int MemoryWordRead(lua_State *List, unsigned int addr) {
096: volatile unsigned short *mmaped;
097: int fd, i;
098: unsigned int pageaddr, offsetmask, pagemask, data;
099:
100: fd = open("/dev/mem",O_RDWR);
101: if(fd < 0) {
102: lua_pushstring(List, "Cannot open /dev/mem");
103: lua_error(List);
104: }
105: offsetmask = PAGE_SIZE;
106: offsetmask--;
107: pagemask = ~offsetmask;
108: pageaddr = addr & pagemask;
109: mmaped = (volatile unsigned short *)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, pageaddr);
110: close(fd);
111: if(mmaped == MAP_FAILED) {
112: lua_pushstring(List, "Cannot mmap");
113: lua_error(List);
114: }
115: data = mmaped[(addr & offsetmask) >> 1] & 0xffff;
116: munmap((char*)mmaped, PAGE_SIZE);
117: return data;
118: }
119:
120: static void MemoryLongWrite(lua_State *List, unsigned int addr, unsigned int data) {
121: volatile unsigned int *mmaped;
122: int fd, i;
123: unsigned int pageaddr, offsetmask, pagemask;
124:
125: fd = open("/dev/mem",O_RDWR);
126: if(fd < 0) {
127: lua_pushstring(List, "Cannot open /dev/mem");
128: lua_error(List);
129: }
130: offsetmask = PAGE_SIZE;
131: offsetmask--;
132: pagemask = ~offsetmask;
133: pageaddr = addr & pagemask;
134: mmaped = (volatile unsigned int *)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, pageaddr);
135: close(fd);
136: if(mmaped == MAP_FAILED) {
137: lua_pushstring(List, "Cannot mmap");
138: lua_error(List);
139: }
140: mmaped[(addr & offsetmask) >> 2] = data;
141: munmap((char*)mmaped, PAGE_SIZE);
142: }
143:
144: static unsigned int MemoryLongRead(lua_State *List, unsigned int addr) {
145: volatile unsigned int *mmaped;
146: int fd, i;
147: unsigned int pageaddr, offsetmask, pagemask, data;
148:
149: fd = open("/dev/mem",O_RDWR);
150: if(fd < 0) {
151: lua_pushstring(List, "Cannot open /dev/mem");
152: lua_error(List);
153: }
154: offsetmask = PAGE_SIZE;
155: offsetmask--;
156: pagemask = ~offsetmask;
157: pageaddr = addr & pagemask;
158: mmaped = (volatile unsigned int *)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, pageaddr);
159: close(fd);
160: if(mmaped == MAP_FAILED) {
161: lua_pushstring(List, "Cannot mmap");
162: lua_error(List);
163: }
164: data = mmaped[(addr & offsetmask) >> 2];
165: munmap((char*)mmaped, PAGE_SIZE);
166: return data;
167: }
168:
169: int memory(lua_State *List) {
170: lua_Number addr, data;
171: char *type;
172: int argc;
173: void (*writefunc)(lua_State *, unsigned int, unsigned int);
174: unsigned int (*readfunc)(lua_State *, unsigned int);
175:
176: argc = lua_gettop(List);
177: if(argc < 2 || argc > 3) {
178: lua_pushstring(List, "Usage: memory byte|word|long address ?data?");
179: lua_error(List);
180: }
181: type = lua_tostring(List, 1);
182: if(strcmp(type, "byte") == 0) {
183: writefunc = MemoryByteWrite;
184: readfunc = MemoryByteRead;
185: } else if(strcmp(type, "word") == 0) {
186: writefunc = MemoryWordWrite;
187: readfunc = MemoryWordRead;
188: } else if(strcmp(type, "long") == 0) {
189: writefunc = MemoryLongWrite;
190: readfunc = MemoryLongRead;
191: } else {
192: lua_pushstring(List, "Usage: memory byte|word|long address ?data?");
193: lua_error(List);
194: }
195: addr = lua_tonumber(List, 2);
196: if(argc == 3) {
197: data = lua_tonumber(List, 3);
198: (*writefunc)(List, (unsigned int)addr, (unsigned int)data);
199: }
200: data = (lua_Number)((*readfunc)(List, (unsigned int)addr));
201: lua_pushnumber(List, data);
202: return 1;
203: }
リスト2の22~167行目まではハードウェアアクセスを行う関数で、
SHプロセッサではメモリアクセスが1バイトアクセス、
外部から呼び出させる関数はmemory関数で、
第1引数はメモリアクセスのサイズを文字列で受け取り
第2引数は物理メモリアドレスでlua_
もし、
コンパイルと実行
共有ライブラリのコンパイルはPC上で行い、
# sh3-linux-gcc -shared -Wl,-soname,memory.so -o memory.so memory.c
できあがったmemory.
# lua Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio > func = package.loadlib("./memory.so", "memory") > func("byte",0xa4000136,0x36) ^C #
上記の例では、
tcl言語からのハードウェアアクセス
C言語での記述
前半でtcl言語からC言語の関数を呼び出す方法について説明しましたので、
ハードウェアアクセスを行うtcl言語から呼び出されるC言語の関数は、
001: #include <sys/types.h>
002: #include <sys/stat.h>
003: #include <fcntl.h>
004: #include <unistd.h>
005: #include <stdlib.h>
006: #include <stdio.h>
007: #include <string.h>
008: #include <sys/mman.h>
009: #include <asm/page.h>
010: #include <tcl.h>
011:
012: static int MemoryByteWrite(Tcl_Interp *interp, unsigned int addr, unsigned int data);
013: static int MemoryByteRead(Tcl_Interp *interp, unsigned int addr, unsigned int *data);
014: static int MemoryWordWrite(Tcl_Interp *interp, unsigned int addr, unsigned int data);
015: static int MemoryWordRead(Tcl_Interp *interp, unsigned int addr, unsigned int *data);
016: static int MemoryLongWrite(Tcl_Interp *interp, unsigned int addr, unsigned int data);
017: static int MemoryLongRead(Tcl_Interp *interp, unsigned int addr, unsigned int *data);
018: static int MemoryCmd(ClientData clientdata, Tcl_Interp *interp, int argc, char **argv);
019:
020: static int MemoryByteWrite(Tcl_Interp *interp, unsigned int addr, unsigned int data) {
021: volatile unsigned char *mmaped;
022: int fd, i;
023: unsigned int pageaddr, offsetmask, pagemask;
024:
025: fd = open("/dev/mem",O_RDWR);
026: if(fd < 0) {
027: interp->result = "Cannot open /dev/mem";
028: return TCL_ERROR;
029: }
030: offsetmask = PAGE_SIZE;
031: offsetmask--;
032: pagemask = ~offsetmask;
033: pageaddr = addr & pagemask;
034: mmaped = (volatile unsigned char*)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, pageaddr);
035: close(fd);
036: if(mmaped == MAP_FAILED) {
037: interp->result = "Cannot mmap";
038: return TCL_ERROR;
039: }
040: mmaped[addr & offsetmask] = data;
041: munmap((char*)mmaped, PAGE_SIZE);
042: return TCL_OK;
043: }
044:
045: static int MemoryByteRead(Tcl_Interp *interp, unsigned int addr, unsigned int *data) {
046: volatile unsigned char *mmaped;
047: int fd, i;
048: unsigned int pageaddr, offsetmask, pagemask;
049:
050: fd = open("/dev/mem",O_RDWR);
051: if(fd < 0) {
052: interp->result = "Cannot open /dev/mem";
053: return TCL_ERROR;
054: }
055: offsetmask = PAGE_SIZE;
056: offsetmask--;
057: pagemask = ~offsetmask;
058: pageaddr = addr & pagemask;
059: mmaped = (volatile unsigned char*)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, pageaddr);
060: close(fd);
061: if(mmaped == MAP_FAILED) {
062: interp->result = "Cannot mmap";
063: return TCL_ERROR;
064: }
065: *data = mmaped[addr & offsetmask] & 0xff;
066: munmap((char*)mmaped, PAGE_SIZE);
067: return TCL_OK;
068: }
069:
070: static int MemoryWordWrite(Tcl_Interp *interp, unsigned int addr, unsigned int data) {
071: volatile unsigned short *mmaped;
072: int fd, i;
073: unsigned int pageaddr, offsetmask, pagemask;
074:
075: fd = open("/dev/mem",O_RDWR);
076: if(fd < 0) {
077: interp->result = "Cannot open /dev/mem";
078: return TCL_ERROR;
079: }
080: offsetmask = PAGE_SIZE;
081: offsetmask--;
82 pagemask = ~offsetmask;
083: pageaddr = addr & pagemask;
084: mmaped = (volatile unsigned short *)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, pageaddr);
085: close(fd);
086: if(mmaped == MAP_FAILED) {
087: interp->result = "Cannot mmap";
088: return TCL_ERROR;
089: }
090: mmaped[(addr & offsetmask) >> 1] = data;
091: munmap((char*)mmaped, PAGE_SIZE);
092: return TCL_OK;
093: }
094:
095: static int MemoryWordRead(Tcl_Interp *interp, unsigned int addr, unsigned int *data) {
096: volatile unsigned short *mmaped;
097: int fd, i;
098: unsigned int pageaddr, offsetmask, pagemask;
099:
100: fd = open("/dev/mem",O_RDWR);
101: if(fd < 0) {
102: interp->result = "Cannot open /dev/mem";
103: return TCL_ERROR;
104: }
105: offsetmask = PAGE_SIZE;
106: offsetmask--;
107: pagemask = ~offsetmask;
108: pageaddr = addr & pagemask;
109: mmaped = (volatile unsigned short *)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, pageaddr);
110: close(fd);
111: if(mmaped == MAP_FAILED) {
112: interp->result = "Cannot mmap";
113: return TCL_ERROR;
114: }
115: *data = mmaped[(addr & offsetmask) >> 1] & 0xffff;
116: munmap((char*)mmaped, PAGE_SIZE);
117: return TCL_OK;
118: }
119:
120: static int MemoryLongWrite(Tcl_Interp *interp, unsigned int addr, unsigned int data) {
121: volatile unsigned int *mmaped;
122: int fd, i;
123: unsigned int pageaddr, offsetmask, pagemask;
124:
125: fd = open("/dev/mem",O_RDWR);
126: if(fd < 0) {
127: interp->result = "Cannot open /dev/mem";
128: return TCL_ERROR;
129: }
130: offsetmask = PAGE_SIZE;
131: offsetmask--;
132: pagemask = ~offsetmask;
133: pageaddr = addr & pagemask;
134: mmaped = (volatile unsigned int *)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, pageaddr);
135: close(fd);
136: if(mmaped == MAP_FAILED) {
137: interp->result = "Cannot mmap";
138: return TCL_ERROR;
139: }
140: mmaped[(addr & offsetmask) >> 2] = data;
141: munmap((char*)mmaped, PAGE_SIZE);
142: return TCL_OK;
143: }
144:
145: static int MemoryLongRead(Tcl_Interp *interp, unsigned int addr, unsigned int *data) {
146: volatile unsigned int *mmaped;
147: int fd, i;
148: unsigned int pageaddr, offsetmask, pagemask;
149:
150: fd = open("/dev/mem",O_RDWR);
151: if(fd < 0) {
152: interp->result = "Cannot open /dev/mem";
153: return TCL_ERROR;
154: }
155: offsetmask = PAGE_SIZE;
156: offsetmask--;
157: pagemask = ~offsetmask;
158: pageaddr = addr & pagemask;
159: mmaped = (volatile unsigned int *)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, pageaddr);
160: close(fd);
161: if(mmaped == MAP_FAILED) {
162: interp->result = "Cannot mmap";
163: return TCL_ERROR;
164: }
165: *data = mmaped[(addr & offsetmask) >> 2];
166: munmap((char*)mmaped, PAGE_SIZE);
167: return TCL_OK;
168: }
169:
170: static int MemoryCmd(ClientData clientdata, Tcl_Interp *interp, int argc, char **argv) {
171: unsigned int addr, data;
172: int error;
173: int (*writefunc)(Tcl_Interp*, unsigned int, unsigned int);
174: int (*readfunc)(Tcl_Interp*, unsigned int, unsigned int *);
175:
176: if(argc < 3 || argc > 4) {
177: interp->result = "Usage: memory byte|word|long address ?data?";
178: return TCL_ERROR;
179: }
180: if(strcmp(argv[1], "byte") == 0) {
181: writefunc = MemoryByteWrite;
182: readfunc = MemoryByteRead;
183: } else if(strcmp(argv[1], "word") == 0) {
184: writefunc = MemoryWordWrite;
185: readfunc = MemoryWordRead;
186: } else if(strcmp(argv[1], "long") == 0) {
187: writefunc = MemoryLongWrite;
188: readfunc = MemoryLongRead;
189: } else {
190: interp->result = "Usage: memory byte|word|long address ?data?";
191: return TCL_ERROR;
192: }
193: error = Tcl_GetInt(interp, argv[2], &addr);
194: if(error != TCL_OK) return error;
195: if(argc == 4) {
196: error = Tcl_GetInt(interp, argv[3], &data);
197: if(error != TCL_OK) return error;
198: error = (*writefunc)(interp, addr, data);
199: if(error != TCL_OK) return error;
200: }
201: error = (*readfunc)(interp, addr, &data);
202: if(error != TCL_OK) return error;
203: sprintf(interp->result, "%d", data);
204: return TCL_OK;
205: }
206:
207: int Memory_Init(Tcl_Interp *interp) {
208: Tcl_CreateCommand(interp, "memory", MemoryCmd, (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
209: Tcl_PkgProvide(interp, "memory", "1.1");
210: return TCL_OK;
211: }
リスト3の20~168行目まではハードウェアアクセスを行う関数で、
SHプロセッサではメモリアクセスが1バイトアクセス、
Tcl_
外部から呼び出させる関数は初期化関数 Memory_
tcl言語処理系からMemoryCmd関数へ渡される引数は2つまたは3つでそれ以外はエラー終了にしています
第2引数は、
もし、
コンパイルと実行
共有ライブラリのコンパイルはPC上で行い、
# sh3-linux-gcc -shared -Wl,-soname,memory.so -o memory.so memory.c
できあがったmemory.
# tclsh % load ./memory.so Memory % format %x [memory byte 0xa4000136 0x36] 36 % exit #
上記の例ではSH7706LSRの付属LEDを点灯させる処理を行っています。
次回は
次回はSH7706LSRのLinux上でハードウェア割り込みを扱う方法について解説します。