TCL/TK windows下配置

TCL语言是“Tool Command Language”的简写。 TCL很好学,功能很强大。TCL经常被用于快速原型开发,脚本编程,GUI 和测试等方面。TCL念作“踢叩” “tickle”.

本文不做过多TCL/TK的介绍,大体介绍下在windows x86的系统怎么搭建tcl/tk的开发环境。

1:下载tcl/tk的开发包

当前很多软件都提供了tcl/tk的开发包,但是相对比较好的,涵盖比较丰富的,也就是官网提供的:Action TCL,这个开发工具不仅含有预编译好的tcl 和 tk的核心工具,还包含了很多丰富的扩展等等,方便初学者开发使用。

下载地址在Active TCL的官网即可找到:http://www.activestate.com/activetcl/downloads 现在Active TCL已经有商业版的了,不过我们下载社区版本的即可。我的系统是windows x86的,所以,我选择windows x86对应的安装包,点击下载,我下载的版本是ActiveTcl8.5.11.1.295590-win32-ix86-threaded.exe,可以在这里下载,我提供一个连接:

http://sdrv.ms/MxvPel

下载之后,然后点击安装即可,我安装到D:\Tcl,安装完成之后,我们打开windows的cmd命令窗口,然后输入:tclsh  回车,然后便有tcl/tk的提示符“%”,然后我们输入:exit便会退出这个提示符。

下面我们简单写个脚本,大概了解下再windows下怎么去运行tcl脚本:

①在D盘下建立一个文件,名字为:hello.tcl,内容为:

puts stdout {Hello, World!}

 

②打开windows的cmd命令行,进入D盘,然后输入:

tclsh hello.tcl

 

③然后我们可以看到结果:

Hello, World!

上述我们便可看到如何在windows下去运行一个tcl脚本了吧?

2:更多的开发方式

TCL/TK可以完美的集成到Eclipse的plugin中,请参考我的另一篇文章:

http://www.jyguagua.com/?p=184

3:附录

下面我提供了一个自己编译好的TCL/TK的chm学习文档,想学习的可以把下载了:

http://www.jyguagua.com/go/download.php?id=2

mini 2440 PWM定时器(led闪烁)

PWM

mini 2440 PWM定时器(led闪烁) 代码下载

http://www.jyguagua.com/bbs/forum.php?mod=viewthread&tid=187&fromuid=1

PWM定时器的原理:

S3C2440的定时器一共有5个,均是16位定时器.根据S3C2440手册,我们可以知道0,1,2,3四个定时器都有PWM(Pulse Width Modulation)功能, 即他们都有一个输出引脚,可以通过定时器来控制引脚周期性的高低电平变化;定时器4没有输出引脚.

定时器部件的时钟源为:PCLK,首先通过两个8位的预分频处理器降低频率:定时器0,1共用一个预分频处理器, 定时器2,3,4共用第二个预分频处理器,紧接着第二级别分频处理器可以产生:2,4,8,16的分频以及外接TCLK0/TCLK1.每个定时器可以从这5中频率中选择.

定时器内部控制逻辑如下:

1:程序初始化,设定:TCMPBn,TCNTBn这两个寄存器,代表的是定时器n的比较值跟初始计数值;

2:随之设置TCON寄存器启动定时器,这时,TCMPBn,TCMTBn这两个寄存器的值被装入TCMPn, TCMTn的寄存器中,在定时器n的工作频率下,TCMTn开始减1,其值可以通过读取TCNTOn寄存器得知;

3:当TCNTn的值等于TCMPn的时候,定时器n的输出管脚TOUTn反转,TCNTn继续减1计数;

4:当TCNTn的值减到0时, 其输出管脚TOUTn再次反转,并触发定时器n的中断(如果中断使能的话);

5:当TCNTn的值为0时,如果再TCON寄存器中将定时器n设为自动加载,则TCMPB0和TCNTB0寄存器的值被自动装入TCMP0和TCNT0寄存器中,下一个计数接着开始.

下面是代码:

head.S

/*中断向量表*/
    b Reset
HandleUndef:
    b HandleUndef
HandleSWI:
    b HandleSWI
HandlePrefetchAbort:
    b HandlePrefetchAbort
HandleDataAbort:
    b HandleDataAbort
HandleNotUsed:
    b HandleNotUsed
    b HandleIRQ
HandleFIQ:
    b HandleFIQ
   
Reset:
    ldr sp, =4096   @下面都是C语言,设置栈
    bl  disable_watch_dog  @关看门狗
    bl  clock_init  @初始化时钟
    bl  memsetup    @初始化Sdram
    bl  copy_steppingstone_to_sdram @拷贝前4k代码到0x30000000处
    ldr pc, =on_sdram   @进入中断

on_sdram:
    msr cpsr_c, #0xd2 @进入中断模式
    ldr sp, =4096   @设置栈,这个是中断模式的栈

    msr     cpsr_c, #0xdf   @进入系统模式
    ldr sp, =0x34000000 @系统模式栈

    bl  init_led    @初始化led,全部关闭
    bl  timer0_init @初始化定时器
    bl  init_irq    @设置irq寄存器
    msr cpsr_c, #0x5f   @开IRQ中断

    ldr lr, =halt_loop
    ldr pc, =main   @调用main函数

halt_loop:
    b   halt_loop

HandleIRQ:
    sub lr, lr, #4
    stmdb   sp!, {r0-r12, lr}

    ldr lr, =int_return
    ldr pc, =Timer0_Handle
int_return:
    ldmia sp!, {r0-r12, pc}^

init.c

#include "s3c2440.h"

void disable_watch_dog(void);
void clock_init(void);
void memsetup(void);
void copy_steppingstone_to_sdram(void);
void init_led(void);
void timer0_init(void);
void init_irq(void);

void disable_watch_dog(void)
{
    WTCON = 0; 
}

void clock_init(void)
{
    CLKDIVN = 0x05;

    __asm__(
        "mrc    p15, 0, r1, c1, c0, 0\n"
        "orr    r1, r1, #0xc0000000\n"
        "mcr    p15, 0, r1, c1, c0, 0\n"
    );

    if ((GSTATUS1 == 0x32410002)) {
        MPLLCON = mini2440PLL;             
    }
}

void memsetup(void)
{
    volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;
    /* 存储控制器13个寄存器的值 */
        p[0] = 0x22011110;     //BWSCON
        p[1] = 0x00000700;     //BANKCON0
        p[2] = 0x00000700;     //BANKCON1
        p[3] = 0x00000700;     //BANKCON2
        p[4] = 0x00000700;     //BANKCON3  
        p[5] = 0x00000700;     //BANKCON4
        p[6] = 0x00000700;     //BANKCON5
        p[7] = 0x00018005;     //BANKCON6
        p[8] = 0x00018005;     //BANKCON7
       
        /* REFRESH,
         * HCLK=12MHz:  0x008C07A3,
         * HCLK=100MHz: 0x008C04F4
         */
        p[9]  = 0x008C04f4;
        p[10] = 0x000000B1;     //BANKSIZE
        p[11] = 0x00000030;     //MRSRB6
        p[12] = 0x00000030;     //MRSRB7

}

void copy_steppingstone_to_sdram(void)
{
    unsigned int *pdwSrc = (unsigned int *)0;
    unsigned int *pdwDest = (unsigned int *)0x30000000;

    while (pdwSrc < (unsigned int *)4096) {
        *pdwDest = *pdwSrc;
        pdwDest++;
        pdwSrc++;
    }
}

void init_led(void)
{
    GPBCON = GPB5_out | GPB6_out | GPB7_out | GPB8_out;
}

void timer0_init(void)
{
    TCFG0 = 99;
    TCFG1 &= 0X02;
    TCNTB0 = 25000;
    TCON |= (1<<1);
    TCON = 0X9;
}

void init_irq(void)
{
    INTMSK &= (~(1<<10));
    INTMOD &= (~(1<<10));
}

interrupt.c

#include "s3c2440.h"

void Timer0_Handle(void)
{
    if (INTOFFSET == 10) {
        GPBDAT = ~(GPBDAT & (0xf << 5));
    }

    SRCPND = 1 << INTOFFSET;
    INTPND = INTPND;
}

interrupt.h

void EINT_Handle();

main.c

int main(void)
{
    while(1);
    return 0;
}

S3C2440.h

/*chip info register*/
#define GSTATUS1 (*(unsigned long *)0x560000b0)

/*watch dog register*/
#define WTCON (*(unsigned long *)0x53000000)

/*clock registers*/
#define CLKDIVN (*(volatile unsigned long *)0x4C000014)
#define MPLLCON (*(volatile unsigned long *)0x4C000004)
#define CLKCON (*(volatile unsigned long *)0x4C00000C)
#define mini2440PLL ((0x7f<<12)|(0x02<<4)|(0x00))

/*sdram registers*/
#define MEM_CTL_BASE 0x48000000
#define SDRAM_BASE 0x30000000

/*gpio led registers*/
#define GPBCON (*(volatile unsigned long *)0x56000010)
#define GPBDAT (*(volatile unsigned long *)0x56000014)
#define GPB5_out (1<<(5*2))
#define GPB6_out (1<<(6*2))
#define GPB7_out (1<<(7*2))
#define GPB8_out (1<<(8*2))

/*key interrupt io registers*/
#define GPG0_eint (2)
#define GPG3_eint (2<<(3*2))
#define GPG5_eint (2<<(5*2))
#define GPG6_eint (2<<(6*2))

/*interrupt registers*/
#define INTMSK (*(volatile unsigned long *)0X4A000008)
#define INTOFFSET (*(volatile unsigned long *)0x4A000014)
#define INTPND (*(volatile unsigned long *)0X4A000010)
#define INTMOD (*(volatile unsigned long *)0X4A000004)
#define SRCPND (*(volatile unsigned long *)0X4A000000)

/*timer registers*/
#define TCFG0 (*(volatile unsigned long *)0x51000000)
#define TCFG1 (*(volatile unsigned long *)0x51000004)
#define TCON (*(volatile unsigned long *)0x51000008)
#define TCNTB0 (*(volatile unsigned long *)0x5100000C)

timer.lds

SECTIONS {
    . = 0x30000000;
    .text          :   { *(.text) }
    .rodata ALIGN(4) : {*(.rodata)}
    .data ALIGN(4) : { *(.data) }
    .bss ALIGN(4)  : { *(.bss)  *(COMMON) }
}

main.c

int main(void)
{
    while(1);
    return 0;
}

 

mini2440 sdram裸机程序编写

China_Samsung_S3C2440_ARM9_Board_Mini2440_256MB201075843083

程序主要的任务是:初始化SDRAM,然后将nand flash的前4k代码拷贝到SDRAM的前4k. 根据S3C2440的手册,我们知道bank6,7是可以外接SDRAM的,那么sdram的起始地址是:0×30000000(参考芯片手册即可).

初始化SDRAM,往往需要配置如下的几个寄存器:

1:BWSCON

这个寄存器包括三部分:STx, WSx, DWx.

STx:启动/禁止 SDRAM的数据掩码引脚,对于SDRAM,此位为0; 对于SRAM,此位为1;

WSx:是否使用存储的WAIT信号, 通常我们设置为0;

DWx: 使用两位来设置响应的bank的位宽,对于我们的开发板, bank 6,7是32位宽的,而bank1~bank5是16位宽的

2:BANKCONx(x为0~5)

这个寄存器用来控制BANK0~BANK5外接设备的访问时序,使用默认的0×0700即可满足开发板所接个外设的要求.

3:BANKCONx(x为6,7)

在开发板8个bank中,只有BANK 6,7是可以外接SDRAM或SRAM的, 所以这个寄存器BANK 6,7与BANK0~5的配置是有所不同的.

MT: 用于设置是SDRAM还是SRAM,我们是SDRAM

Trcd: RAS to CAS delay, 设为推荐值:0b01

SCAN:SDRAM的列地址位数, 对于本开发板,我们的列数是9

4:REFRESH

REFEN: 禁止/开启 SDRAM刷新的功能

TREFMD: SDRAM的刷新模式

Trp:设为0即可

Tsrc: 设为默认值0b11即可

Refresh Counter: 这个计算有个公式:

R_CNT = 2 ^11 + 1 -SDRAM时钟频率(MHz) * SDRAM刷新周期(uS)

SDRAM的刷新周期可以在SDRAM的手册HY57V561620.pdf上可以看到:8192 refresh cycles / 64ms,所以刷新周期 =  64ms/8192 = 7.8125 us

SDRAM的始终频率等于晶振频率12MHz

现在可以计算出R_CNT = 2 ^11 + 1 -12 * 7.8125 =  1955

5:BANKSIZE

这个寄存器我们在乎的是BK76MAP,设置BANK 6,7的大小,我们开发板的大小事64MB的.

6:MRSRBx

这个寄存器能修改的只有位CL, 这个是SDRAM的一个时间参数,我们的板子支持的是2clocks 或者 3 clocks.

代码如下:

head.S

.equ MEM_CTL_BASE, 0X48000000
.equ SDRAM_BASE, 0x30000000

.text
.global _start

_start:
    bl disable_watch_dog
    bl memsetup
    bl copy_steppingstone_to_sdram
    ldr pc, =on_sdram

on_sdram:
    ldr sp, =0x34000000
    bl main

halt_loop:
    b halt_loop

disable_watch_dog:
    mov r1, #0x53000000
    mov r2, #0
    str r2, [r1]
    mov pc, lr

copy_steppingstone_to_sdram:
    mov r1, #0
    ldr r2, =SDRAM_BASE
    mov r3, #4*1024

l:
    ldr r4, [r1], #4
    str r4, [r2], #4
    cmp r1, r3
    bne l
    mov pc, lr

memsetup:

    mov r1, #MEM_CTL_BASE
    adrl r2, mem_cfg_val
    add r3, r1, #52

L:
    ldr r4, [r2], #4
    str r4, [r1], #4
    cmp r1, r3
    bne L
    mov pc, lr

.align 4
mem_cfg_val:
    .long 0x22011110 @BWSCON
    .long 0x00000700 @BANKCON0
    .long 0x00000700 @BANKCON1
    .long 0x00000700 @BANKCON2
    .long 0x00000700 @BANKCON3
    .long 0x00000700 @BANKCON4
    .long 0x00000700 @BANKCON5
    .long 0x00018005 @BANKCON6
    .long 0x00018005 @BANKCON7
    .long 0x008c07a3 @REFRESH
    .long 0x000000b1 @BANKSIZE
    .long 0x00000030 @MRSRB6
    .long 0x00000030 @MRSRB7

leds.c

#define GPBCON      (*(volatile unsigned long *)0x56000010)
#define GPBDAT      (*(volatile unsigned long *)0x56000014)

#define GPB5_out    (1<<(5*2))
#define GPB6_out    (1<<(6*2))
#define GPB7_out    (1<<(7*2))
#define GPB8_out    (1<<(8*2))

void wait(volatile unsigned long dly)
{
    for (; dly > 0; dly--);
}

int main(void)
{
    unsigned long i = 1;

    GPBCON = GPB7_out|GPB5_out|GPB6_out|GPB8_out;

    while (1) {
        wait(30000);
        GPBDAT = ~(i << 5);
        if (++i == 8)
            i = 1;
    }
}

Makefile

sdram.bin: head.S leds.c
    arm-elf-gcc -c leds.c -o leds.o
    arm-elf-gcc -c head.s -o head.o
    arm-elf-ld -Ttext=0x30000000 head.o leds.o -o sdram_elf
    arm-elf-objcopy -O binary -S sdram_elf sdram.bin
    arm-elf-objdump -D -m arm sdram_elf > sdram.dis
clean:
    rm -f sdram.dis sdram.bin sdram_elf *.o

mini2440 按键中断点亮led灯裸机代码

先把代码贴上,后续再去进行详细介绍,总共需要这么几个文件:

head.S, init.c, interrupt.c, main.c, Makefile

详情可以从这个地方下载:

mini2440 按键中断点亮led灯裸机代码http://www.jyguagua.com/bbs/forum.php?mod=viewthread&tid=184&fromuid=1

head.S内容:

@********************************
@file: head.S
@功能:初始化,设置中断模式,系统模式,设置好中断处理函数
@********************************

.extern main
.text
.global _start
_start:
@*******************************
@这段代码只核心写中断向量
@*******************************

    b Reset

@0x04:未定义指令终止模式的向量地址
HandleUndef:
    b   HandleUndef

@定义软中断的向量地址
HandleSWI:
    b   HandleSWI

@定义欲取址中断异常向量地址
HandlePrefectchAbort:
    b   HandlePrefectchAbort

@定义数据中止异常
HandleDataAbort:
    b   HandleDataAbort

@定义保留向量地址
HandleNotUsed:
    b   HandleNotUsed
   
@定义中断的向量地址
    b   HandleIRQ

@定义快中断的向量地址
HandleFIQ:
    b   HandleFIQ

@reset的处理函数
Reset:
    ldr sp, =4096 @先设置栈指针,以下都是C语言需要设置栈指针
    bl  disable_watch_dog @跳到init.c文件去执行

    msr cpsr_c, #0xd2 @进入中断模式
    ldr sp, =3072 @中断模式的栈指针定义

    msr cpsr_c, #0xdf @进入系统模式
    ldr sp, =4096 @设置系统模式的栈指针

    bl  init_led @初始化led,使其均输出状态而且熄灭,在init.c
    bl  init_irq @调用init.c中的init_irq函数,初始化中断各个寄存器配置
    msr cpsr_c, #0x5f @开启IRQ中断

    ldr lr, =halt_loop @设置返回地址
    ldr pc, =main @跳到main函数执行

halt_loop:
    b   halt_loop

HandleIRQ:
    sub lr, lr, #4 @计算中断的返回地址
    stmdb   sp!, {r0-r12, lr} @保存使用到的寄存器


    ldr lr, =int_return
    ldr pc, =EINT_Handle @调用中断处理函数

int_return:
    ldmia   sp!, {r0-r12, pc}^

init.c 内容:

/*初始化GPIO引脚为外部中断
 * GPIO引脚用作外部中断,默认为低电平触发,IRQ方式
 * */
#define WTCON (*(unsigned long *)0x53000000)
#define GPGCON (*(unsigned long *)0x56000060)
#define EINTMASK (*(unsigned long *)0x560000a4)
#define INTMSK (*(unsigned long *)0X4A000008)

/*led寄存器*/
#define GPBCON (*(unsigned long *)0x56000010)
#define GPBDAT (*(unsigned long *)0x56000014)
#define GPBUP (*(unsigned long *)0x56000018)

void disable_watch_dog(void)
{
    //关闭看门狗
    WTCON = 0;
}

void init_led(void)
{
    //设置led引脚为输出引脚,初始化都熄灭而且上拉电阻disable
    GPBCON = (1 << 10) | (1 << 12) | (1 << 14) | (1 << 16);
    GPBDAT |= (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8);
    GPBUP |= (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8);
}

void init_irq()
{
    GPGCON = (10) | (10 << 6) | (10 << 10) | (10 << 12); //设置EINT8, 11, 13, 14
    INTMSK &= (~(1 << 5)); //开启总中断屏蔽
    EINTMASK &= (~(1 << 8)) &  (~(1 << 11)) & (~(1 << 13)) & (~(1 << 14)); //开启对应的外部中断
}

interrupt.c内容:

#define INTOFFSET (*(unsigned long *)0x4A000014)
#define EINTPEND (*(unsigned long *)0x560000a8)
#define GPBCON (*(unsigned long *)0x56000010)
#define GPBDAT (*(unsigned long *)0x56000014)
#define GPBUP (*(unsigned long *)0x56000018)
#define INTPND (*(unsigned long *)0X4A000010)
#define SRCPND (*(unsigned long *)0X4A000000)

void EINT_Handle()
{
    unsigned long oft = INTOFFSET;
    unsigned long val;
   
    switch (oft)
    {
        case 5:
        {
            GPBDAT |= (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8);           
            //判断到底是哪个按键按下的
            val = EINTPEND;

            if (val & (1 << 8)) {
            //点亮第一个灯   
                GPBDAT &= ~(1 << 5);
            }
            if (val & (1 << 11)) {
            //点亮第二个灯   
                GPBDAT &= ~(1 << 6);
            }
            if (val & (1 << 13)) {
            //点亮第三个灯   
                GPBDAT &= ~(1 << 7);
            }
            if (val & (1 << 14)) {
            //点亮第四个灯   
                GPBDAT &= ~(1 << 8);
            }
            break;
        }
        default:
            break;
    }

    //清除中断
    if (oft == 5) {
        EINTPEND = (1 << 8) | (1 << 11) | (1 << 13) | (1 << 14);   
    }
    SRCPND = 1 << oft;
    INTPND = 1 << oft;


}

main.c内容如下:

int main()
{
    while(1);
    return 0;
}

Makefile的内容如下:

objs := head.o init.o interrupt.o main.o

int.bin: $(objs)
    arm-linux-ld -Ttext 0x00000000 -o int_elf $^
    arm-linux-objcopy -O binary -S int_elf $@
    arm-linux-objdump -D -m arm int_elf > int.dis
   
%.o:%.c
    arm-linux-gcc -Wall -O2 -c -o $@ $<

%.o:%.S
    arm-linux-gcc -Wall -O2 -c -o $@ $<

clean:
    rm -f int.bin int_elf int.dis *.o

Source Insight支持ARM汇编高亮设置

show

今天把uboot代码添加到SI的项目里面,打开*.S的文件的时候,发现还是黑白色的,感觉很不舒服,我使用的SI的版本是: ver 3.50,通过百度,找到了解决的办法,方法如下:

1:想让*.s 或者 *.S文件高亮,那么需要这么做,在工具栏菜单,选择”Options->Document Options”,然后在打开的弹窗里面,有个Document Type的下拉菜单,我们找到”X86 Asm source file”, 然后在右边的file filter加上*.s,*.S ,然后点击close即可看到arm代码高亮了;

2:如果想拥有看C语言一样有索引的功能,可以方便的查找函数标签等等,那么这么做,在工具栏菜单,选择”Options->Document Options”,然后在打开的弹窗里面,有个Document Type的下拉菜单,我们找到”C source file”, 然后在右边的file filter加上*.s,*.S ,然后点击close即可看到arm代码有了索引的功能;

最后的效果图如下: