Merge pull request #39 from prife/sim-module

simulator: mingw and  app module support
This commit is contained in:
Bernard Xiong 2013-02-26 17:44:33 -08:00
commit 76bdeb3ec3
24 changed files with 1398 additions and 9 deletions

View File

@ -12,8 +12,8 @@ if os.getenv('RTT_RTGUI'):
else:
# set the rtgui root directory by hand
# empty string means use the RTGUI in svn
# RTT_RTGUI = os.path.normpath(r'F:\Project\git\rt-gui\components\rtgui')
RTT_RTGUI =''
RTT_RTGUI = os.path.normpath(r'F:\Project\git\rt-gui\components\rtgui')
# RTT_RTGUI =''
sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
from building import *
@ -51,13 +51,34 @@ if rtconfig.PLATFORM == 'cl':
env.Append(LINKFLAGS=rtconfig.LFLAGS)
env['LIBS']=libs
env['CPPDEFINES']=definitions
elif rtconfig.PLATFORM == 'mingw':
libs = Split('''
winmm
gdi32
winspool
comdlg32
advapi32
shell32
ole32
oleaut32
uuid
odbc32
odbccp32
''')
TARGET = 'rtthread-win32.' + rtconfig.TARGET_EXT
env = Environment(tools = ['mingw'],
AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS,
AR = rtconfig.AR, ARFLAGS = '-rc',
LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
env['LIBS']=libs
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
else:
TARGET = 'rtthread'
env.Append(CCFLAGS=rtconfig.CFLAGS)
env.Append(LINKFLAGS=rtconfig.LFLAGS)
env.Append(LIBS=['m'])
# prepare building environment
objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False, remove_components=['rtgui'])
@ -85,8 +106,42 @@ if GetDepend('RT_USING_RTGUI'):
if GetDepend('RT_USING_TC'):
objs = objs + SConscript(RTT_ROOT + '/examples/kernel/SConscript', variant_dir = 'build/tc/kernel', duplicate=0)
# build program
program = env.Program(TARGET, objs)
def ObjRemove(objs, remove):
for item in objs:
# print type(item), os.path.basename(str(item))
if os.path.basename(str(item)) in remove:
objs.remove(item)
return
# build program -shared
if GetDepend('RT_USING_MODULE'):
# Remove module.c in $RTT_ROOT/src
ObjRemove(objs, ['module.obj', 'module.o'])
AddOption('--def',
dest='def',
action='store_true',
default=False,
help='create rthread.def of rtthread.dll on windows')
if GetOption('def'):
if rtconfig.PLATFORM != 'mingw':
print "scons error: `--def' can only work with mingw"
exit(1)
env['LINKFLAGS'] = rtconfig.DEFFILE_LFLAGS
env.SharedLibrary("rtthread.dll", objs)
program = ''
else:
if rtconfig.PLATFORM == 'cl':
objs += ['rtthread.def']
elif rtconfig.PLATFORM == 'mingw':
rtconfig.POST_ACTION = 'del /Q rtthread.lib \n rename librtthread.a rtthread.lib\n'
# rtconfig.POST_ACTION = 'lib /machine:i386 /def:rtthread.def /out:rtthread.lib'
env.SharedLibrary("rtthread.dll", objs)
program = env.Program(TARGET, 'dummy.c', LIBS='rtthread', LIBPATH='.')
else:
program = env.Program(TARGET, objs)
# end building
EndBuilding(TARGET, program)

View File

@ -6,6 +6,8 @@ src = Glob('*.c')
# remove no need file.
if GetDepend('RT_USING_DFS_WINSHAREDIR') == False:
SrcRemove(src, 'dfs_win32.c')
if GetDepend('RT_USING_MODULE') == False:
SrcRemove(src, ['module_win32.c'])
CPPPATH = [cwd, str(Dir('#'))]
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)

View File

@ -27,6 +27,22 @@
#include <WinError.h>
#include <windows.h>
#if defined(__MINGW32__) && defined(_NO_OLDNAMES)
#define O_RDONLY _O_RDONLY
#define O_WRONLY _O_WRONLY
#define O_RDWR _O_RDWR
#define O_ACCMODE _O_ACCMODE
#define O_APPEND _O_APPEND
#define O_CREAT _O_CREAT
#define O_TRUNC _O_TRUNC
#define O_EXCL _O_EXCL
#define O_TEXT _O_TEXT
#define O_BINARY _O_BINARY
#define O_TEMPORARY _O_TEMPORARY
#define O_NOINHERIT _O_NOINHERIT
#define O_SEQUENTIAL _O_SEQUENTIAL
#define O_RANDOM _O_RANDOM
#endif
/*
* RT-Thread DFS Interface for win-directory as an disk device
*/
@ -132,6 +148,14 @@ static char *winpath_dirdup(char *des, const char *src)
return path;
}
/* This function can convert the path in rt-thread/dfs to the path in windows */
char * dfs_win32_dirdup(char * path)
{
char * file_path;
file_path = winpath_dirdup(WIN32_DIRDISK_ROOT, path);
return file_path;
}
static int dfs_win32_open(struct dfs_fd *file)
{
int fd;

View File

@ -53,7 +53,7 @@ void rt_hw_win32_low_cpu(void)
#endif
}
#ifdef _WIN32
#ifdef _MSC_VER
#ifndef _CRT_TERMINATE_DEFINED
#define _CRT_TERMINATE_DEFINED
_CRTIMP __declspec(noreturn) void __cdecl exit(__in int _Code);

4
bsp/simulator/dummy.c Normal file
View File

@ -0,0 +1,4 @@
int dummy_main()
{
return 0;
}

222
bsp/simulator/mingw.ld Normal file
View File

@ -0,0 +1,222 @@
/* Default linker script, for normal executables */
OUTPUT_FORMAT(pei-i386)
SEARCH_DIR("/usr/local/mingw32/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");
SECTIONS
{
/* Make the virtual address and file offset synced if the alignment is
lower than the target page size. */
. = SIZEOF_HEADERS;
. = ALIGN(__section_alignment__);
.text __image_base__ + ( __section_alignment__ < 0x1000 ? . : __section_alignment__ ) :
{
*(.init)
*(.text)
*(SORT(.text$*))
*(.glue_7t)
*(.glue_7)
___CTOR_LIST__ = .; __CTOR_LIST__ = . ;
LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*)); LONG (0);
___DTOR_LIST__ = .; __DTOR_LIST__ = . ;
LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*)); LONG (0);
*(.fini)
/* ??? Why is .gcc_exc here? */
*(.gcc_exc)
PROVIDE (etext = .);
*(.gcc_except_table)
}
/* setction information for finsh shell begin */
. = ALIGN(__section_alignment__);
FSymTab () :
{
___fsymtab_start = .; __fsymtab_start = .;
KEEP(*(FSymTab))
___fsymtab_end = .; __fsymtab_end = .;
}
. = ALIGN(__section_alignment__);
VSymTab () :
{
___vsymtab_start = .; __vsymtab_start = .;
KEEP(*(VSymTab))
___vsymtab_end = .; __vsymtab_end = .;
}
/* setction information for finsh shell end */
/* The Cygwin32 library uses a section to avoid copying certain data
on fork. This used to be named ".data". The linker used
to include this between __data_start__ and __data_end__, but that
breaks building the cygwin32 dll. Instead, we name the section
".data_cygwin_nocopy" and explictly include it after __data_end__. */
.data BLOCK(__section_alignment__) :
{
__data_start__ = . ;
*(.data)
*(.data2)
*(SORT(.data$*))
*(.jcr)
__data_end__ = . ;
*(.data_cygwin_nocopy)
}
.rdata BLOCK(__section_alignment__) :
{
*(.rdata)
*(SORT(.rdata$*))
*(.eh_frame)
___RUNTIME_PSEUDO_RELOC_LIST__ = .;
__RUNTIME_PSEUDO_RELOC_LIST__ = .;
*(.rdata_runtime_pseudo_reloc)
___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
__RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
}
.pdata BLOCK(__section_alignment__) :
{
*(.pdata)
}
.bss BLOCK(__section_alignment__) :
{
__bss_start__ = . ;
*(.bss)
*(COMMON)
__bss_end__ = . ;
}
.edata BLOCK(__section_alignment__) :
{
*(.edata)
}
/DISCARD/ :
{
*(.debug$S)
*(.debug$T)
*(.debug$F)
*(.drectve)
}
.idata BLOCK(__section_alignment__) :
{
/* This cannot currently be handled with grouped sections.
See pe.em:sort_sections. */
SORT(*)(.idata$2)
SORT(*)(.idata$3)
/* These zeroes mark the end of the import list. */
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
SORT(*)(.idata$4)
SORT(*)(.idata$5)
SORT(*)(.idata$6)
SORT(*)(.idata$7)
}
.CRT BLOCK(__section_alignment__) :
{
___crt_xc_start__ = . ;
*(SORT(.CRT$XC*)) /* C initialization */
___crt_xc_end__ = . ;
___crt_xi_start__ = . ;
*(SORT(.CRT$XI*)) /* C++ initialization */
___crt_xi_end__ = . ;
___crt_xl_start__ = . ;
*(SORT(.CRT$XL*)) /* TLS callbacks */
/* ___crt_xl_end__ is defined in the TLS Directory support code */
___crt_xp_start__ = . ;
*(SORT(.CRT$XP*)) /* Pre-termination */
___crt_xp_end__ = . ;
___crt_xt_start__ = . ;
*(SORT(.CRT$XT*)) /* Termination */
___crt_xt_end__ = . ;
}
.tls BLOCK(__section_alignment__) :
{
___tls_start__ = . ;
*(.tls)
*(.tls$)
*(SORT(.tls$*))
___tls_end__ = . ;
}
.endjunk BLOCK(__section_alignment__) :
{
/* end is deprecated, don't use it */
PROVIDE (end = .);
PROVIDE ( _end = .);
__end__ = .;
}
.rsrc BLOCK(__section_alignment__) :
{
*(.rsrc)
*(SORT(.rsrc$*))
}
.reloc BLOCK(__section_alignment__) :
{
*(.reloc)
}
.stab BLOCK(__section_alignment__) (NOLOAD) :
{
*(.stab)
}
.stabstr BLOCK(__section_alignment__) (NOLOAD) :
{
*(.stabstr)
}
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section. Unlike other targets that fake this by putting the
section VMA at 0, the PE format will not allow it. */
/* DWARF 1.1 and DWARF 2. */
.debug_aranges BLOCK(__section_alignment__) (NOLOAD) :
{
*(.debug_aranges)
}
.debug_pubnames BLOCK(__section_alignment__) (NOLOAD) :
{
*(.debug_pubnames)
}
/* DWARF 2. */
.debug_info BLOCK(__section_alignment__) (NOLOAD) :
{
*(.debug_info) *(.gnu.linkonce.wi.*)
}
.debug_abbrev BLOCK(__section_alignment__) (NOLOAD) :
{
*(.debug_abbrev)
}
.debug_line BLOCK(__section_alignment__) (NOLOAD) :
{
*(.debug_line)
}
.debug_frame BLOCK(__section_alignment__) (NOLOAD) :
{
*(.debug_frame)
}
.debug_str BLOCK(__section_alignment__) (NOLOAD) :
{
*(.debug_str)
}
.debug_loc BLOCK(__section_alignment__) (NOLOAD) :
{
*(.debug_loc)
}
.debug_macinfo BLOCK(__section_alignment__) (NOLOAD) :
{
*(.debug_macinfo)
}
/* SGI/MIPS DWARF 2 extensions. */
.debug_weaknames BLOCK(__section_alignment__) (NOLOAD) :
{
*(.debug_weaknames)
}
.debug_funcnames BLOCK(__section_alignment__) (NOLOAD) :
{
*(.debug_funcnames)
}
.debug_typenames BLOCK(__section_alignment__) (NOLOAD) :
{
*(.debug_typenames)
}
.debug_varnames BLOCK(__section_alignment__) (NOLOAD) :
{
*(.debug_varnames)
}
/* DWARF 3. */
.debug_ranges BLOCK(__section_alignment__) (NOLOAD) :
{
*(.debug_ranges)
}
}

View File

@ -21,6 +21,10 @@
#elif defined(__GNUC__)
#define RT_USING_NOLIBC
#if defined(__MINGW32__)
#define _NO_OLDNAMES /* to ignore: mode_t in sys/type.h */
#endif
#endif
/* SECTION: basic kernel options */
@ -83,6 +87,7 @@
/* SECTION: Device System */
/* Using Device System */
#define RT_USING_DEVICE
#define RT_USING_DEVICE_IPC
/* #define RT_USING_UART1 */
/* SECTION: Console options */
@ -94,11 +99,14 @@
/* SECTION: component options */
#define RT_USING_COMPONENTS_INIT
/* SECTION: APP MODULE */
#define RT_USING_MODULE
/* SECTION: MTD interface options */
/* using mtd nand flash */
#define RT_USING_MTD_NAND
/* using mtd nor flash */
#define RT_USING_MTD_NOR
/* #define RT_USING_MTD_NOR */
/* SECTION: finsh, a C-Express shell */
#define RT_USING_FINSH

View File

@ -1,7 +1,7 @@
# toolchains options
ARCH='sim'
#CROSS_TOOL='msvc' or 'gcc' or 'mingw' (mingw is not supported yet!)
CROSS_TOOL='msvc'
CROSS_TOOL='mingw'
# cross_tool provides the cross compiler
# EXEC_PATH is the compiler execute path
@ -10,11 +10,20 @@ if CROSS_TOOL == 'gcc':
PLATFORM = 'gcc'
EXEC_PATH = '/usr/bin/gcc'
if CROSS_TOOL == 'msvc':
elif CROSS_TOOL == 'mingw':
CPU = 'win32'
PLATFORM = 'mingw'
EXEC_PATH = r'D:\Program Files\CodeBlocks\MinGW\bin'
elif CROSS_TOOL == 'msvc':
CPU = 'win32'
PLATFORM = 'cl'
EXEC_PATH = ''
else :
print "bad CROSS TOOL!"
exit(1)
BUILD = 'debug'
#BUILD = ''
@ -48,6 +57,35 @@ if PLATFORM == 'gcc':
POST_ACTION = ''
elif PLATFORM == 'mingw':
# toolchains
PREFIX = ''
CC = PREFIX + 'gcc'
AS = PREFIX + 'gcc'
AR = PREFIX + 'ar'
LINK = PREFIX + 'gcc'
TARGET_EXT = 'exe'
SIZE = PREFIX + 'size'
OBJDUMP = PREFIX + 'objdump'
OBJCPY = PREFIX + 'objcopy'
DEVICE = ' -ffunction-sections -fdata-sections'
DEVICE = ' '
CFLAGS = DEVICE
AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp'
DEFFILE_LFLAGS = DEVICE + ' -Wl,-Map=rtthread-win32.map,--output-def,rtthread.def -T mingw.ld '
LFLAGS = DEVICE + ' -Wl,-Map=rtthread-win32.map -T mingw.ld '
CPATH = ''
LPATH = ''
if BUILD == 'debug':
CFLAGS += ' -g -O0 -gdwarf-2'
AFLAGS += ' -gdwarf-2'
else:
CFLAGS += ' -O2'
POST_ACTION = ''
elif PLATFORM == 'cl':
# toolchains
PREFIX = ''

View File

@ -0,0 +1,84 @@
import os
import sys
import SCons.cpp
import rtconfig
if os.getenv('RTT_ROOT'):
RTT_ROOT = os.getenv('RTT_ROOT')
else:
RTT_ROOT = os.path.normpath(os.getcwd() + '/../..')
if os.getenv('RTT_RTGUI'):
RTT_RTGUI = os.getenv('RTT_RTGUI')
else:
# set the rtgui root directory by hand
# empty string means use the RTGUI in svn
RTT_RTGUI = os.path.normpath(r'F:\Project\git\rt-gui\components\rtgui')
# RTT_RTGUI =''
sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
from building import *
Export('RTT_ROOT')
# add target option
AddOption('--app',
dest='app',
nargs=1, type='string',
action='store',
metavar='DIR',
help='installation prefix')
# add target option
AddOption('--type',
dest='type',
nargs=1, type='string',
action='store',
metavar='DIR',
help='installation prefix')
app = GetOption('app')
env = Environment()
CPPPATH = [
RTT_ROOT + '/include',
RTT_ROOT + '/bsp/' + rtconfig.BSP,
RTT_ROOT + '/components/finsh',
RTT_ROOT + '/components/libdl',
RTT_ROOT + '/components/external/ftk/ftk/src/os/rt-thread',
RTT_ROOT + '/components/external/ftk/ftk/src/demos',
RTT_ROOT + '/components/external/ftk/ftk/apps/common',
RTT_ROOT + '/components/external/ftk/ftk/src',
RTT_ROOT + '/components/dfs',
RTT_ROOT + '/components/dfs/include',
RTT_ROOT + '/components/libc/newlib',
RTT_ROOT + '/components/external/cairo/cairo-1.10.2/src',
RTT_ROOT + '/components/external/cairo/'
]
if RTT_RTGUI:
RTGUI_ROOT = RTT_RTGUI
else:
RTGUI_ROOT = RTT_ROOT + '/components/rtgui'
RTGUI_PATH = [
RTGUI_ROOT + '/include',
RTGUI_ROOT + '/common',
RTGUI_ROOT + '/server',
RTGUI_ROOT + '/widgets',
]
CPPPATH += RTGUI_PATH
env.Append(CCFLAGS=rtconfig.CFLAGS)
env.Append(LINKFLAGS=rtconfig.LFLAGS)
env.Append(CPPPATH=CPPPATH)
env.Append(LIBS='rtthread', LIBPATH='../')
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
PrepareModuleBuilding(env, RTT_ROOT)
#dir = app + '/build/' + rtconfig.BSP
dir = app + '/build/'
objs = SConscript(app + '/Sconscript', variant_dir=dir, duplicate=0)
TARGET = dir + '/' + app + '.' + rtconfig.TARGET_EXT
# build program
#env.Program(TARGET, objs)
env.SharedLibrary(TARGET, objs)

View File

@ -0,0 +1,7 @@
import rtconfig
Import('RTT_ROOT')
from building import *
src = Glob('*.c')
group = DefineGroup('', src, depend = [''])
Return('group')

View File

@ -0,0 +1,30 @@
#include <rtthread.h>
static int a = 0;
static int b = 1000000;
int c = 100;
static void function(int count1, int count2, int count3)
{
rt_kprintf("Hello RT-Thread %d %d\n", count1, count2, count3);
}
int main(void)
{
int i;
rt_kprintf("application entry\n");
rt_kprintf("[addr]a-0x%x,b-0x%x,c-0x%x\n", &a, &b, &c);
rt_kprintf("[value]a-%d,b-%d,c-%d\n", a, b, c);
for(i=0; i<100; i++)
{
a++;
b--;
c++;
function(a, c, b );
}
return 0;
}

View File

@ -0,0 +1,7 @@
import rtconfig
Import('RTT_ROOT')
from building import *
src = Glob('*.c')
group = DefineGroup('', src, depend = [''])
Return('group')

View File

@ -0,0 +1,74 @@
#include <rtthread.h>
#include <rtgui/rtgui.h>
#include <rtgui/rtgui_app.h>
#include <rtgui/widgets/window.h>
#include <rtgui/widgets/label.h>
#include <rtgui/driver.h>
/* 在LCD上创建一个主窗口这是第一个窗口 */
static void win_thread_entry(void *parameter)
{
struct rtgui_app *app;
struct rtgui_win *win;
struct rtgui_label *label;
struct rtgui_rect rect;
app = rtgui_app_create(rt_thread_self(), "MyApp");
RT_ASSERT(app != RT_NULL);
/* create a full screen window */
rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), &rect);
win = rtgui_win_create(RT_NULL, "MainWin", &rect,
RTGUI_WIN_STYLE_NO_BORDER | RTGUI_WIN_STYLE_NO_TITLE);
if (win == RT_NULL)
{
rtgui_app_destroy(app);
return;
}
/* 建立一个label内容为helloworld */
label = rtgui_label_create("Hello World!");
/* 设置label的位置这里是绝对坐标 */
rect.x1 = 0;
rect.y1 = 100;
rect.x2 = 240;
rect.y2 = 140;
rtgui_widget_set_rect(RTGUI_WIDGET(label), &rect);
rt_kprintf("bc: %x\n", RTGUI_WIDGET_BACKGROUND(label));
rt_kprintf("fc: %x\n", RTGUI_WIDGET_FOREGROUND(label));
#if 0
RTGUI_WIDGET_BACKGROUND(label) = 0;
RTGUI_WIDGET_FOREGROUND(label) = RTGUI_RGB(0xFF, 0xFF, 0);
#endif
/*添加label到主窗口*/
rtgui_container_add_child(RTGUI_CONTAINER(win), RTGUI_WIDGET(label));
/* 显示主窗口 */
rtgui_win_show(win, RT_FALSE);
/* 循环 */
rtgui_app_run(app);
rtgui_win_destroy(win);
rtgui_app_destroy(app);
rt_kprintf("MyApp Quit.\n");
}
int main()
{
rt_thread_t tid;
tid = rt_thread_create("win", win_thread_entry, RT_NULL,
2048, 20, 20);
if (tid != RT_NULL)
{
rt_thread_startup(tid);
}
return 0;
}

View File

@ -0,0 +1,51 @@
# bsp name
BSP = 'simulator'
# toolchains
EXEC_PATH = ''
PREFIX = ''
TARGET_EXT = 'dll'
AS = PREFIX + 'cl'
CC = PREFIX + 'cl'
AR = PREFIX + 'cl'
LINK = PREFIX + 'cl'
AFLAGS = ''
CFLAGS = ''
LFLAGS = ''
BUILD = 'debug'
if BUILD == 'debug':
CFLAGS += ' /MTd'
LFLAGS += ' /DEBUG'
else:
CFLAGS += ' /MT'
LFLAGS += ''
CFLAGS += ' /ZI /Od /W 3 /WL'
LFLAGS += ' /DEF:rttapp.def /SUBSYSTEM:CONSOLE /MACHINE:X86'
#LFLAGS += ' /DEF:rttapp.def /SUBSYSTEM:WINDOWS /MACHINE:X86' #/ENTRY:mainCRTStartup
CPATH = ''
LPATH = ''
'''
EXEC_PATH = 'C:/Program Files/CodeSourcery/Sourcery G++ Lite/bin'
PREFIX = 'arm-none-eabi-'
CC = PREFIX + 'gcc'
CXX = PREFIX + 'g++'
AS = PREFIX + 'gcc'
AR = PREFIX + 'ar'
LINK = PREFIX + 'gcc'
TARGET_EXT = 'so'
SIZE = PREFIX + 'size'
OBJDUMP = PREFIX + 'objdump'
OBJCPY = PREFIX + 'objcopy'
DEVICE = ' -mcpu=arm920t'
CFLAGS = DEVICE + ' -O0 -fPIC -DFTK_AS_PLUGIN -DRT_THREAD '
AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp'
LFLAGS = DEVICE + ' -Wl,-z,max-page-size=0x4 -shared -fPIC -nostdlib -s'
CPATH = ''
LPATH = ''
'''

View File

@ -0,0 +1,3 @@
LIBRARY app
EXPORTS
main

View File

@ -0,0 +1,7 @@
import rtconfig
Import('RTT_ROOT')
from building import *
src = Glob('*.c')
group = DefineGroup('', src, depend = [''])
Return('group')

View File

@ -0,0 +1,271 @@
#include <string.h>
#include <stdlib.h>
#include <rtthread.h>
#include "snake.h"
#define ASSERT_RET(x, ret) \
do{ \
if (x) \
return ret; \
}while(0)
rt_list_t snake_head;
SNAKE_DIR prevdir, newdir;
static SNAKE_DIR dir_adjust(SNAKE_DIR dir)
{
if ((SNAKE_DIR_UP == prevdir && SNAKE_DIR_DOWN != dir)
|| (SNAKE_DIR_DOWN == prevdir && SNAKE_DIR_UP != dir)
|| (SNAKE_DIR_LEFT == prevdir && SNAKE_DIR_RIGHT != dir)
|| (SNAKE_DIR_RIGHT == prevdir && SNAKE_DIR_LEFT != dir)
)
{
newdir = dir;
}
else
{
rt_kprintf("dirction change error\n\r");
}
return newdir;
}
static void across_XY(point_t *node, const map_t *map)
{
RT_ASSERT(node != RT_NULL && map != RT_NULL);
// 如果长度超出当前边框则可以穿越墙到对面
node->x = (node->x + map->width) % map->width;
node->y = (node->y + map->height) % map->height;
}
static SYS_STE node_update(snake_t *tail, const point_t *node, map_t *map)
{
SYS_STE ret;
point_t *pos;
RT_ASSERT(tail != RT_NULL && node != RT_NULL && map != RT_NULL);
pos = map->snake_flush;
pos[0].x = pos[0].y = -1;
pos[1].x = pos[1].y = -1;
ret = (SYS_STE)map->range[node->y * map->width + node->x];
if (FOOD == map->range[node->y * map->width + node->x])
{
// 吃一个食物增加一个节点
snake_t *new = (snake_t *)rt_malloc(sizeof(snake_t));
if (!new)
return NORMAL;
pos[0] = *node;
new->body = *node;
rt_list_insert_after(&snake_head, &new->list);
}
else if (NORMAL == map->range[node->y * map->width + node->x])
{
// 将尾巴修改后拿到头部,其他不变
rt_list_remove(&tail->list);
map->range[tail->body.y * map->width + tail->body.x] = NORMAL;
pos[0] = *node;
pos[1] = tail->body;
tail->body = *node;
rt_list_insert_after(&snake_head, &tail->list);
}
map->range[node->y * map->width + node->x] = OVER;
if (ret != OVER)
prevdir = newdir;
return ret;
}
map_t *map_init(rt_uint32_t width, rt_uint32_t heigth)
{
map_t *map = rt_malloc(sizeof(map_t));
if (map != RT_NULL)
{
map->range = rt_malloc(heigth * width);
if (!map->range)
{
rt_free(map);
map = RT_NULL;
}
else
{
map->width = width;
map->height = heigth;
memset(map->range, NORMAL, heigth * width);
}
}
return map;
}
// 构造一条指定长度的蛇在指定点
rt_bool_t snake_init(const point_t *start, const int length, const SNAKE_DIR dir, map_t *map)
{
rt_int32_t i;
rt_int32_t inc_x, inc_y;
point_t old = *start;
ASSERT_RET(!map || !start, RT_FALSE);
rt_list_init(&snake_head);
if (dir == SNAKE_DIR_UP || dir == SNAKE_DIR_DOWN)
{
if (map->height <= length)
return RT_FALSE;
inc_x = 0;
inc_y = dir == SNAKE_DIR_DOWN ? 1 : -1; // 反向延长身子,头部在指定位置
old.y -= inc_y;
}
else
{
if (map->width <= length)
return RT_FALSE;
inc_y = 0;
inc_x = dir == SNAKE_DIR_RIGHT ? -1 : 1;
old.x -= inc_x;
}
for (i = 0; i < length; i++)
{
snake_t *new = (snake_t *)rt_malloc(sizeof(snake_t));
if (!new)
return RT_FALSE;
new->body.y = inc_y + old.y;
new->body.x = inc_x + old.x;
// 如果长度超出当前边框则可以穿越墙到对面
across_XY(&new->body, map);
map->range[new->body.y * map->width + new->body.x] = OVER;
old = new->body;
rt_list_insert_before(&snake_head, &new->list);
}
prevdir = dir;
return RT_TRUE;
}
// 构造出食物
rt_bool_t food_init(map_t *map, rt_uint32_t max_num)
{
point_t food;
#ifndef FOOD_TIMEOUT
#define FOOD_TIMEOUT 10
#endif
rt_uint32_t timeout, num;
ASSERT_RET(!map, RT_FALSE);
num = 0;
timeout = rt_tick_get();
srand(rand());
map->food_flush[0].x = map->food_flush[0].y = -1;
do
{
food.x = rand() % map->width;
food.y = rand() % map->height;
if (map->range[food.y * map->width + food.x] == NORMAL)
{
map->food_flush[0] = food;
map->range[food.y * map->width + food.x] = FOOD;
num++;
}
}
while (num < max_num && rt_tick_get() - timeout < FOOD_TIMEOUT);
return num;
}
void map_deinit(map_t *map)
{
if (map)
{
if (map->range)
{
rt_free(map->range);
map->range = RT_NULL;
}
rt_free(map);
}
}
void snake_deinit(void)
{
snake_t *node;
while (!rt_list_isempty(&snake_head))
{
node = rt_list_entry(snake_head.prev, snake_t, list);
rt_list_remove(&node->list);
rt_free(node);
}
}
void food_deinit(void)
{
}
SYS_STE snake_step(SNAKE_DIR dir, map_t *map)
{
snake_t *tail, *head;
point_t node;
ASSERT_RET(!map, RT_FALSE);
dir = dir_adjust(dir);
// 取出头尾两个节点,其他节点不需要改变
tail = rt_list_entry(snake_head.prev, snake_t, list);
head = rt_list_entry(snake_head.next, snake_t, list);
node = head->body;
// 构造一个新的蛇头坐标
switch (dir)
{
case SNAKE_DIR_UP:
case SNAKE_DIR_DOWN:
node.y = head->body.y + (dir == SNAKE_DIR_DOWN ? -1 : 1);
break;
case SNAKE_DIR_LEFT:
case SNAKE_DIR_RIGHT:
node.x = head->body.x + (dir == SNAKE_DIR_RIGHT ? 1 : -1);
break;
}
across_XY(&node, map);
return node_update(tail, &node, map);
}
rt_bool_t snake_restart(const point_t *start, const int length, const SNAKE_DIR dir, map_t *map)
{
ASSERT_RET(!map || !start, RT_FALSE);
snake_deinit();
memset(map->range, NORMAL, map->width * map->height);
return snake_init(start, length, dir, map);
}

View File

@ -0,0 +1,68 @@
#ifndef _SNAKE_H_
#define _SNAKE_H_
#include <rtthread.h>
#define snake_length_max 20 //最大蛇长
#define snake_length_init 3 //初始化蛇长
#define snake_room_size_hight 8 //房子高 0-255 建议>8
#define snake_room_size_widht 8 //房子宽 0-255 建议>8
#define snake_init_pointx 1
#define snake_init_pointy 2
typedef struct
{
rt_int32_t x, y;
} point_t;
typedef struct
{
rt_int32_t width; // max x
rt_int32_t height; // max y
rt_uint8_t *range; // map, map->range[y * map->width + x]
point_t snake_flush[2];
point_t food_flush[1];
} map_t;
typedef enum
{
SNAKE_DIR_UP,
SNAKE_DIR_DOWN,
SNAKE_DIR_LEFT,
SNAKE_DIR_RIGHT
} SNAKE_DIR;
typedef enum
{
FOOD, // 吃到水果
OVER, // 咬到自身
NORMAL // 正常行动
} SYS_STE;
typedef struct
{
point_t body;
rt_list_t list;
} snake_t;
// 构造一个地图
map_t *map_init(rt_uint32_t width, rt_uint32_t heigth);
// 构造一条指定长度的蛇在指定点
rt_bool_t snake_init(const point_t *start, const int length, const SNAKE_DIR dir, map_t *map);
// 构造出食物
rt_bool_t food_init(map_t *map, rt_uint32_t max_num);
void map_deinit(map_t *map);
void snake_deinit(void);
void food_deinit(void);
SYS_STE snake_step(SNAKE_DIR dir, map_t *map);
rt_bool_t snake_restart(const point_t *start, const int length, const SNAKE_DIR dir, map_t *map);
#endif

View File

@ -0,0 +1,397 @@
#include <string.h>
#include <rtthread.h>
#include <rtgui/rtgui.h>
#include <rtgui/rtgui_app.h>
#include <rtgui/widgets/container.h>
#include <rtgui/widgets/window.h>
#include <rtgui/widgets/button.h>
#include "snake.h"
#define LATTICE_SIZE (20)
#define FOOD_MAX (8)
#define WALL_COLOR RTGUI_RGB(255, 0, 0)
#define SNAKE_COLOR RTGUI_RGB(0, 100, 200)
#define SNAKE_HEAD_COLOR RTGUI_RGB(180, 70, 130)
#define BACKGROUND_COLOR RTGUI_RGB(153, 153, 0)
#define FOOD_COLOR RTGUI_RGB(128, 0, 0)
static rtgui_timer_t *timer;
static rt_size_t room_size_x, room_size_y;
static rt_size_t lattice_size_x, lattice_size_y;
static struct rtgui_rect room_rect, lattice_rect;
map_t *map;
SNAKE_DIR run_state;
rt_int32_t snake_len;
rt_int32_t food_num;
point_t second_node;
static void snake_fill_lattice(struct rtgui_dc *dc,
rt_uint32_t x,
rt_uint32_t y,
rtgui_color_t color)
{
struct rtgui_rect rect;
// coordinate conversion
y = (lattice_size_y - 1) - y;
RTGUI_DC_BC(dc) = color;
rect.x1 = lattice_rect.x1 + (LATTICE_SIZE * x);
rect.x2 = rect.x1 + LATTICE_SIZE;
rect.x1 += 2;
rect.y1 = lattice_rect.y1 + (LATTICE_SIZE * y);
rect.y2 = rect.y1 + LATTICE_SIZE;
rect.y1 += 2;
rtgui_dc_fill_rect(dc, &rect);
}
static void snake_draw(struct rtgui_widget *widget)
{
struct rtgui_dc *dc;
struct rtgui_rect rect;
rt_uint32_t i;
dc = rtgui_dc_begin_drawing(widget);
if (dc == RT_NULL)
{
rt_kprintf("dc == RT_NULL\r\n");
return;
}
/* get room size, run once frist. */
if ((room_size_x == 0) || (room_size_y == 0))
{
rt_size_t tmp;
rtgui_widget_get_rect(widget, &rect);
rt_kprintf("rect => x1:%d x2:%d, y1:%d y2:%d\r\n", rect.x1, rect.x2, rect.y1, rect.y2);
room_size_x = rect.x2 - rect.x1;
room_size_y = rect.y2 - rect.y1;
memcpy(&room_rect, &rect, sizeof(struct rtgui_rect));
rt_kprintf("room_rect => x1:%d x2:%d, y1:%d y2:%d\r\n",
room_rect.x1, room_rect.x2,
room_rect.y1, room_rect.y2);
lattice_size_x = (room_rect.x2 - room_rect.x1) / LATTICE_SIZE;
lattice_size_y = (room_rect.y2 - room_rect.y1) / LATTICE_SIZE;
lattice_size_x -= 2;
lattice_size_y -= 2;
rt_kprintf("lattice_size_x:%d lattice_size_y:%d\r\n",
lattice_size_x,
lattice_size_y);
tmp = (room_rect.x2 - room_rect.x1) - (LATTICE_SIZE * lattice_size_x);
lattice_rect.x1 = room_rect.x1 + (tmp / 2);
lattice_rect.x2 = lattice_rect.x1 + (LATTICE_SIZE * lattice_size_x);
tmp = (room_rect.y2 - room_rect.y1) - (LATTICE_SIZE * lattice_size_y);
lattice_rect.y1 = room_rect.y1 + (tmp / 2);
lattice_rect.y2 = lattice_rect.y1 + (LATTICE_SIZE * lattice_size_y);
rt_kprintf("lattice_rect => x1:%d x2:%d, y1:%d y2:%d\r\n",
lattice_rect.x1, lattice_rect.x2,
lattice_rect.y1, lattice_rect.y2);
/* create snake. */
{
point_t start;
map = map_init(lattice_size_x, lattice_size_y);
if (map != RT_NULL)
{
start.x = snake_init_pointx;
start.y = snake_init_pointy;
run_state = SNAKE_DIR_DOWN;
if (snake_init(&start, snake_length_init, run_state, map))
{
food_num = 1;
food_init(map, food_num);
}
else
{
map_deinit(map);
map = RT_NULL;
}
}
}
}
RTGUI_DC_BC(dc) = BACKGROUND_COLOR;
rtgui_dc_fill_rect(dc, &room_rect);
memcpy(&rect, &lattice_rect, sizeof(struct rtgui_rect));
rect.x2 += 1;
rect.y2 += 1;
RTGUI_DC_FC(dc) = WALL_COLOR;
rtgui_dc_draw_rect(dc, &rect);
for (i = 1; i < lattice_size_y; i++)
{
memcpy(&rect, &lattice_rect, sizeof(struct rtgui_rect));
rect.x1 += 1;
rect.x2 -= 1;
rtgui_dc_draw_horizontal_line(dc, rect.x1, rect.x2,
rect.y1 + (LATTICE_SIZE * i));
}
for (i = 1; i < lattice_size_x; i++)
{
memcpy(&rect, &lattice_rect, sizeof(struct rtgui_rect));
rect.y1 += 1;
rect.y2 -= 1;
rtgui_dc_draw_vertical_line(dc, rect.x1 + (LATTICE_SIZE * i),
rect.y1, rect.y2);
}
/* draw snake. */
{
rt_int32_t x, y;
rt_bool_t first_node = RT_TRUE;
for (y = 0; y < map->height; y++)
{
for (x = 0; x < map->width; x++)
{
switch (map->range[y * map->width + x])
{
case NORMAL:
break;
case FOOD:
snake_fill_lattice(dc, x, y, FOOD_COLOR);
break;
case OVER:
if (first_node)
{
first_node = RT_FALSE;
second_node.x = x;
second_node.y = y;
snake_fill_lattice(dc, x, y, SNAKE_HEAD_COLOR);
}
else
{
snake_fill_lattice(dc, x, y, SNAKE_COLOR);
}
break;
}
}
}
}
rtgui_dc_end_drawing(dc);
return;
}
static void snake_update(struct rtgui_widget *widget)
{
struct rtgui_dc *dc;
rt_int32_t x, y;
rt_uint32_t i;
dc = rtgui_dc_begin_drawing(widget);
if (dc == RT_NULL)
{
rt_kprintf("dc == RT_NULL\r\n");
return;
}
snake_fill_lattice(dc, second_node.x, second_node.y, SNAKE_COLOR);
second_node = map->snake_flush[0];
for (i = 0; i < 3; i++)
{
if (i < 2)
{
x = map->snake_flush[i].x;
y = map->snake_flush[i].y;
}
else
{
x = map->food_flush[0].x;
y = map->food_flush[0].y;
}
if ((x >= 0) && (y >= 0))
{
switch (map->range[(map->width * y) + x])
{
case NORMAL:
snake_fill_lattice(dc, x, y, BACKGROUND_COLOR);
break;
case FOOD:
snake_fill_lattice(dc, x, y, FOOD_COLOR);
break;
case OVER:
if (0 == i)
snake_fill_lattice(dc, x, y, SNAKE_HEAD_COLOR);
else
snake_fill_lattice(dc, x, y, SNAKE_COLOR);
break;
}
}
}
rtgui_dc_end_drawing(dc);
return;
}
static void snake_handler(struct rtgui_widget *widget, rtgui_event_t *event)
{
struct rtgui_event_kbd *ekbd;
ekbd = (struct rtgui_event_kbd *) event;
if (ekbd->type == RTGUI_KEYDOWN)
{
switch (ekbd->key)
{
case RTGUIK_UP:
rt_kprintf("RTGUIK_UP\r\n");
run_state = SNAKE_DIR_UP;
break;
case RTGUIK_DOWN:
rt_kprintf("RTGUIK_DOWN\r\n");
run_state = SNAKE_DIR_DOWN;
break;
case RTGUIK_LEFT:
rt_kprintf("RTGUIK_LEFT\r\n");
run_state = SNAKE_DIR_LEFT;
break;
case RTGUIK_RIGHT:
rt_kprintf("RTGUIK_RIGHT\r\n");
run_state = SNAKE_DIR_RIGHT;
break;
default:
break;
}
}
}
static rt_bool_t event_handler(struct rtgui_object *object, rtgui_event_t *event)
{
struct rtgui_widget *widget = RTGUI_WIDGET(object);
rt_kprintf("event_handler\r\n");
if (event->type == RTGUI_EVENT_PAINT)
{
rt_kprintf("RTGUI_EVENT_PAINT\r\n");
rtgui_win_event_handler((struct rtgui_object *)object, event);
snake_draw(widget);
rtgui_timer_start(timer);
}
else if (event->type == RTGUI_EVENT_SHOW)
{
rt_kprintf("RTGUI_EVENT_SHOW\r\n");
rtgui_win_event_handler((struct rtgui_object *)object, event);
snake_draw(widget);
rtgui_timer_start(timer);
}
else if (event->type == RTGUI_EVENT_HIDE)
{
rt_kprintf("RTGUI_EVENT_HIDE\r\n");
rtgui_win_event_handler((struct rtgui_object *)object, event);
rtgui_timer_stop(timer);
}
else if (event->type == RTGUI_EVENT_WIN_DEACTIVATE)
{
rt_kprintf("RTGUI_EVENT_WIN_DEACTIVATE\r\n");
rtgui_win_event_handler((struct rtgui_object *)object, event);
rtgui_timer_stop(timer);
}
else if (event->type == RTGUI_EVENT_KBD)
{
rtgui_win_event_handler((struct rtgui_object *)object, event);
snake_handler(widget, event);
}
else
{
rt_kprintf("event->type:%d\r\n", event->type);
return rtgui_win_event_handler((struct rtgui_object *)object, event);
}
return RT_FALSE;
}
static void timeout(struct rtgui_timer *timer, void *parameter)
{
struct rtgui_widget *widget;
SYS_STE ret;
if (!map)
return;
ret = snake_step(run_state, map);
if (OVER == ret)
return;
if (FOOD == ret)
{
snake_len++;
if (snake_len >= (map->width * map->height) / 3)
{
point_t start;
start.x = snake_init_pointx;
start.y = snake_init_pointy;
run_state = SNAKE_DIR_DOWN;
snake_len = snake_length_init;
if (!snake_restart(&start, snake_len, run_state, map))
{
map_deinit(map);
snake_deinit();
map = RT_NULL;
}
}
food_init(map, 1);
}
widget = RTGUI_WIDGET(parameter);
snake_update(widget);
}
void main(void)
{
struct rtgui_app *application;
struct rtgui_win *win;
rtgui_rect_t rect;
application = rtgui_app_create("sanke_app");
if (application != RT_NULL)
{
rtgui_get_screen_rect(&rect);
rtgui_set_mainwin_rect(&rect);
win = rtgui_mainwin_create(RT_NULL,
"sanke_win",
RTGUI_WIN_STYLE_MAINWIN | RTGUI_WIN_STYLE_DESTROY_ON_CLOSE);
if (win == RT_NULL)
{
rt_kprintf("sanke_win create fail!\r\n");
return;
}
rtgui_object_set_event_handler(RTGUI_OBJECT(win), event_handler);
timer = rtgui_timer_create(RT_TICK_PER_SECOND / 2,
RT_TIMER_FLAG_PERIODIC,
timeout,
(void *)win);
rtgui_win_show(win, RT_TRUE);
//Í˳öºó²Å·µ»Ø
map_deinit(map);
snake_deinit();
food_deinit();
rtgui_app_destroy(application);
}
}

View File

@ -0,0 +1,7 @@
import rtconfig
Import('RTT_ROOT')
from building import *
src = Glob('*.c')
group = DefineGroup('', src, depend = [''])
Return('group')

View File

@ -0,0 +1,20 @@
#include <rtthread.h>
/* rtgui\common\rtgui_object.c */
_declspec(dllimport) void * _rtgui_object;
/* rtgui\common\color.c */
_declspec(dllimport) rt_uint32_t blue;
//extern rt_uint32_t * green;
int main(void)
{
int i;
//rt_kprintf("green = %x, *green", green, *(rt_uint32_t *)green);
rt_kprintf("blue = %x\n", blue);
rt_kprintf("_rtgui_object = %x\n", _rtgui_object);
return 0;
}

View File

@ -21,6 +21,9 @@ struct rt_module_symtab
const char *name;
};
#if defined(_MSC_VER) || defined(__MINGW32__)
#define RTM_EXPORT(symbol)
#else
#define RTM_EXPORT(symbol) \
const char __rtmsym_##symbol##_name[] = #symbol; \
const struct rt_module_symtab __rtmsym_##symbol SECTION("RTMSymTab")= \
@ -28,6 +31,8 @@ const struct rt_module_symtab __rtmsym_##symbol SECTION("RTMSymTab")= \
(void *)&symbol, \
__rtmsym_##symbol##_name \
};
#endif
#else
#define RTM_EXPORT(symbol)
#endif

View File

@ -18,6 +18,9 @@ if rtconfig.PLATFORM == 'iar':
if rtconfig.PLATFORM == 'cl':
src = Glob(path + '/*.c')
if rtconfig.PLATFORM == 'mingw':
src = Glob(path + '/*.c')
CPPPATH = [RTT_ROOT + '/libcpu/' + rtconfig.ARCH + '/' + rtconfig.CPU, RTT_ROOT + '/libcpu/' + rtconfig.ARCH + '/common']
group = DefineGroup(rtconfig.CPU.upper(), src, depend = [''], CPPPATH = CPPPATH)

View File

@ -111,6 +111,7 @@ static DWORD WINAPI ThreadforKeyGet(LPVOID lpParam);
static void SetThreadName(DWORD dwThreadID, char* threadName)
{
#if defined(_MSC_VER)
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = threadName;
@ -124,6 +125,7 @@ static void SetThreadName(DWORD dwThreadID, char* threadName)
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
#endif
}
/*