lindabell 发表于 2011-11-13 10:57:31

学习RT-thread记录

我2011.11.02才开始收集关于RT-thread的资料,到今天已经11天了,其中有两天到济南出差,严格里来说只有9天的时间。
用了7天看编程指南,2天时间看例程。感觉很好,在这里记录一下(可能比较乱),有不对的地方还请见谅!
   RT-thread官网: http://www.rt-thread.org/
   
我是使用版本: RT-Thread 0.4.0 RC1

lindabell 发表于 2011-11-13 11:05:56

1.finsh的所使用

在RT-Thread 0.4.0 RC1里的stm32f10x工程里已经有示例的代码了,只需要重新编译下载到开发板。在串口会有
\ | /
- RT -   Thread Operating System
/ | \ 0.4.0 build Nov 11 2011
2006 - 2011 Copyright by rt-thread team
finsh>>

使用串口输入“list()”发送到串口去,会返回一些函数和变量
--Function List:
set_date         -- set date. e.g: set_date(2010,2,28)
set_time         -- set time. e.g: set_time(23,59,59)
list_date      -- show date and time.
list_mem         -- list memory usage information
hello            -- say hello world
version          -- show RT-Thread version information
list_thread      -- list thread
list_sem         -- list semaphone in system
list_event       -- list event in system
list_mutex       -- list mutex in system
list_mailbox   -- list mail box in system
list_msgqueue    -- list message queue in system
list_mempool   -- list memory pool in system
list_timer       -- list timer in system
list_device      -- list device in system
list             -- list all symbol in system
led            -- set led on or off.
--Variable List:
dummy            -- dummy variable for finsh
        0, 0x00000000
finsh>>

可以根据提示输入,例如set_date(2011,11,13) 设置日期
这就是finsh的感性认识了

lindabell 发表于 2011-11-13 11:10:27

1.2怎么映finsh射到串口2呢(我的串口1需要他用)
参见http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=5191294&bbs_page_no=1&search_mode=3&search_text=lindabell&bbs_id=9999

在board.c修改如下
// <o> Console on USART: <0=> no console <1=>USART 1 <2=>USART 2 <3=> USART 3
//         <i>Default: 1
#define STM32_CONSOLE_USART       2    //原来是1

在rtconfig.c修改如下
/* SECTION: Device System */
/* Using Device System */
#define RT_USING_DEVICE
#define RT_USING_UART2    //原来是#define RT_USING_UART1

#ifdef RT_USING_FINSH
/* init finsh */
finsh_system_init();
finsh_set_device("uart1");
#endif

改为
#ifdef RT_USING_FINSH
/* init finsh */
finsh_system_init();
finsh_set_device("uart2"); //原来是uart1
#endif

好了,这就完成从串口1到串口2了

lindabell 发表于 2011-11-13 11:32:47

2.finsh的底层暂时不理它,它的实现还是比较麻烦的。咱先感受一下hello word 吧

led的移植

我们的应用程序都是从rt_application_init开始的,就像我们变成纯C的main函数一样的。
看看rt_application_init有什么
int rt_application_init()                       //应用程序初始化
{
        rt_thread_t init_thread;

        rt_err_t result;

    /* init led thread */
        result = rt_thread_init(&led_thread,                                                           //led线程
                "led",                                                                                                                //线程名称
                led_thread_entry, RT_NULL,                                                                        //led线程入口 、无参数
                (rt_uint8_t*)&led_stack, sizeof(led_stack),                                //线程堆栈地址 和 堆栈大小
               20, 5);                                                                                            //优先级时间片
        if (result == RT_EOK)                                                                                        //判断是否初始化成功
        {
      rt_thread_startup(&led_thread);                                                                //线程初始化成功了启动线程
        }
       
        result=rt_thread_init(&my_thread,
                                                "my_thread",
                                                my_thread_entery,RT_NULL,
                                                (rt_uint8_t*)my_stack,sizeof(my_stack),
                                                20,5);
        if(result==RT_EOK)
        {
                rt_thread_startup(&my_thread);
        }

#if (RT_THREAD_PRIORITY_MAX == 32)                                                                          //在RT-thread中优先级有256 和 32两种
        init_thread = rt_thread_create("init",
                                                                rt_init_thread_entry, RT_NULL,
                                                                2048, 8, 20);
#else
        init_thread = rt_thread_create("init",
                                                                rt_init_thread_entry, RT_NULL,
                                                                2048, 80, 20);
#endif

        if (init_thread != RT_NULL)
                rt_thread_startup(init_thread);

        return 0;
}

创建了3个线程led、my_thread、init(其中my_thread是我自己创建的)
找到led的入口函数led_thread_entry,发现里面有一个初始化函数的调用rt_hw_led_init();
在找到rt_hw_led_init的实现部分
void rt_hw_led_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(led1_rcc|led2_rcc,ENABLE);

    GPIO_InitStructure.GPIO_Mode= GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Pin   = led1_pin;
    GPIO_Init(led1_gpio, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin   = led2_pin;
    GPIO_Init(led2_gpio, &GPIO_InitStructure);
}

到这里了不用说都知道这么改了,改完编译下载到板子,使用串口调用led函数就会有反应了

tyqhaha 发表于 2011-11-13 12:03:58

最近在看ucos,不过RTT最近听到好多人在说 呵呵

lindabell 发表于 2011-11-13 12:07:06

回复【4楼】tyqhaha
最近在看ucos,不过rtt最近听到好多人在说 呵呵
-----------------------------------------------------------------------
我以前也看过ucos ii,感觉RTT比较好一点

lindabell 发表于 2011-11-13 14:02:43

3创建线程,在例程中只有一个线程,不容易学习线程间的通信

线程有静态和动态之分的
通过rt thread init创建静态线程,使用rt_thread_create创建动态线程
以为我的板子有4个led,所以我创建了4个动态线程
led_tid=rt_thread_create("led1",
                                                        led1_thread_entery,RT_NULL,
                                                        2000,30,5
                                                        );
        if(led_tid!=RT_NULL) rt_thread_startup(led_tid);
       
        led_tid=rt_thread_create("led2",
                                                        led2_thread_entery,RT_NULL,
                                                        2000,29,5
                                                        );
        if(led_tid!=RT_NULL) rt_thread_startup(led_tid);
       
        led_tid=rt_thread_create("led3",
                                                        led3_thread_entery,RT_NULL,
                                                        2000,28,5
                                                        );
        if(led_tid!=RT_NULL) rt_thread_startup(led_tid);
       
        led_tid=rt_thread_create("led4",
                                                        led4_thread_entery,RT_NULL,
                                                        2000,27,5
                                                        );
        if(led_tid!=RT_NULL) rt_thread_startup(led_tid);
static void led4_thread_entery(void* parameter)
{
        //rt_hw_led_init();//初始化io口
        rt_uint32_t e;
        while(1)
        {
                rt_event_recv(pEvent,1<<5,RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR,RT_WAITING_FOREVER,&e);
                rt_mutex_take(pMutex,RT_WAITING_FOREVER);
                rt_hw_led_on(4);
                rt_thread_delay( RT_TICK_PER_SECOND);
                rt_mutex_release(pMutex);
                rt_hw_led_off(4);
                rt_thread_delay( RT_TICK_PER_SECOND );
        }
}
线程入口分别为
static void led1_thread_entery(void* parameter)
{
        rt_hw_led_init();//初始化io口
        while(1)
        {
       
                rt_hw_led_on(1);
                rt_thread_delay( RT_TICK_PER_SECOND);
                rt_hw_led_off(1);
                rt_thread_delay( RT_TICK_PER_SECOND );
       
        }
}

static void led2_thread_entery(void* parameter)
{
        //rt_hw_led_init();//初始化io口
        while(1)
        {
                rt_hw_led_on(2);
                //rt_thread_delay( RT_TICK_PER_SECOND);
                //rt_hw_led_off(2);
                //rt_thread_delay( RT_TICK_PER_SECOND );
       
        }
}

static void led3_thread_entery(void* parameter)
{
        //rt_hw_led_init();//初始化io口
        while(1)
        {
                rt_hw_led_on(3);
                rt_thread_delay( RT_TICK_PER_SECOND);

                rt_hw_led_off(3);
                rt_thread_delay( RT_TICK_PER_SECOND );

        }
}

static void led4_thread_entery(void* parameter)
{
        //rt_hw_led_init();//初始化io口
        rt_uint32_t e;
        while(1)
        {

                rt_hw_led_on(4);
                rt_thread_delay( RT_TICK_PER_SECOND);

                rt_hw_led_off(4);
                rt_thread_delay( RT_TICK_PER_SECOND );
        }
}
怎样就建立好了4个线程
编译下到板子看看有没有这4个线程
\ | /
- RT -   Thread Operating System
/ | \ 0.4.0 build Nov 13 2011
2006 - 2011 Copyright by rt-thread team
finsh>>list_thread()
threadpristatus      sp   stack size max used   left tickerror
-------- ---- ------- ---------- ---------- ---------- ---------- ---
led4   0x1b suspend 0x00000078 0x000007d0 0x00000078 0x00000005 000
led3   0x1c suspend 0x00000078 0x000007d0 0x00000078 0x00000005 000
led2   0x1d ready   0x00000058 0x000007d0 0x00000058 0x00000003 000
led1   0x1e ready   0x00000040 0x000007d0 0x00000040 0x00000005 000
tidle    0x1f ready   0x00000040 0x00000100 0x00000040 0x00000020 000
tshell   0x14 ready   0x00000088 0x00000800 0x000001b0 0x00000006 000
init   0x08 0x00000068 0x00000800 0x000000c0 0x00000013 000
        0, 0x00000000
finsh>>
finsh>>

可以看见led1~4的线程了,说明创建成功了

lindabell 发表于 2011-11-13 14:22:50

4线程间通信
4.1信号量
        信号量是用来解决线程同步和互斥的通用工具,和互斥量类似,信号量也可用作资源互斥访问,但
信号量没有所有者的概念,在应用上比互斥量更广泛。信号量比较简单,不能解决优先级翻转问
题,但信号量是一种轻量级的对象,比互斥量小巧、灵活。因此在很多对互斥要求不严格的系统
中(或者不会造成优先级翻转的情况下),经常使用信号量来管理互斥资源
        信号量我认为就是一个数值,当其为0时表示资源不可用,但不为0时表示资源可以使用。在初始化信号量是要初始化信号量的值。每当一个线程取得信号量时信号量的数值——,当释放信号量时期数值++。所以假如你初始化为1时,说明在同一时间只能一个线程会得到这个信号量。假如2时最多可以被线程获取2次。
        首先说明一个信号量
        static rt_sem_t pSem=RT_NULL;        //信号量
        再在创建线程之前初始化信号量,名为sem,数值为1,基于先进先出模式
        pSem=rt_sem_create("sem",1,RT_IPC_FLAG_FIFO);
        这样我们就有一个信号量了,下面就该使用了
        修改led1和led2
        static void led1_thread_entery(void* parameter)
        {
                rt_hw_led_init();//初始化io口
                while(1)
                {
                  rt_sem_take(pSem,RT_WAITING_FOREVER);
                        rt_hw_led_on(1);
                        rt_thread_delay( RT_TICK_PER_SECOND);
                        rt_hw_led_off(1);
                        rt_thread_delay( RT_TICK_PER_SECOND );
                        rt_sem_release(pSem);
               
                }
        }
       
        static void led2_thread_entery(void* parameter)
        {
                //rt_hw_led_init();//初始化io口
                while(1)
                {
                        rt_sem_take(pSem,RT_WAITING_FOREVER);
                        rt_hw_led_on(2);
                        rt_thread_delay( RT_TICK_PER_SECOND);
                        rt_hw_led_off(2);
                        rt_thread_delay( RT_TICK_PER_SECOND );
                        rt_sem_release(pSem);
                }
        }
        预期的现象是led1亮灭-led2亮灭-led1亮灭 循环的
        list_sem()
        semaphore v   suspend thread
        ----------- --------------
        sem       000 1:led1
        shrx      001 0
        heap      001 0
                0, 0x00000000
        finsh>>
        finsh>>list_sem()
        semaphore v   suspend thread
        ----------- --------------
        sem       000 1:led2
        shrx      001 0
        heap      001 0
                0, 0x00000000
        finsh>>
        finsh>>
       
        从finsh中看可以看出了led1和led2,间隔持有信号量sem

lindabell 发表于 2011-11-13 14:32:00

4.2互斥量
        其实互斥量和信号量的建立差不多的,同样邮箱、事件也多差不多
        建立互斥量
        static rt_mutex_t pMutex;                //互斥量
        初始化互斥量
        pMutex=rt_mutex_create("mutex",RT_IPC_FLAG_FIFO);
        修改代码
        static void led3_thread_entery(void* parameter)
        {
                //rt_hw_led_init();//初始化io口
                while(1)
                {
                        rt_mutex_take(pMutex,RT_WAITING_FOREVER);
                        rt_hw_led_on(3);
                        rt_thread_delay( RT_TICK_PER_SECOND);
                        rt_hw_led_off(3);
                        rt_thread_delay( RT_TICK_PER_SECOND );
                        rt_mutex_release(pMutex);
       
                }
        }
       
        static void led4_thread_entery(void* parameter)
        {
                //rt_hw_led_init();//初始化io口
                rt_uint32_t e;
                while(1)
                {
                        rt_mutex_take(pMutex,RT_WAITING_FOREVER);
                        rt_hw_led_on(4);
                        rt_thread_delay( RT_TICK_PER_SECOND);
       
                        rt_hw_led_off(4);
                        rt_thread_delay( RT_TICK_PER_SECOND );
                        rt_mutex_release(pMutex);
                }
        }
        效果和使用信号量一样的(led3,led4)
        从finsh看
       
       \ | /
        - RT -   Thread Operating System
       / | \ 0.4.0 build Nov 13 2011
       2006 - 2011 Copyright by rt-thread team
        finsh>>list_mutex()
        mutex    owner    hold suspend thread
        -------- -------- ---- --------------
        mutex    led3   0001 1
                0, 0x00000000
        finsh>>
        finsh>>list_mutex()
        mutex    owner    hold suspend thread
        -------- -------- ---- --------------
        mutex    led3   0001 1
                0, 0x00000000
        finsh>>
        finsh>>list_mutex()
        mutex    owner    hold suspend thread
        -------- -------- ---- --------------
        mutex    led3   0001 1
                0, 0x00000000
        finsh>>
        finsh>>list_mutex()
        mutex    owner    hold suspend thread
        -------- -------- ---- --------------
        mutex    led4   0001 1
                0, 0x00000000
        finsh>>
        finsh>>list_mutex()
        mutex    owner    hold suspend thread
        -------- -------- ---- --------------
        mutex    led4   0001 1
                0, 0x00000000
        finsh>>
        finsh>>

lindabell 发表于 2011-11-13 14:48:31

4.3事件
        事件看可以多个触发一个,即发生几件事才会触发或其中一件事发生也可以触发
        建立事件
        static rt_event_t pEvent;                //事件
        事件初始化
        pEvent=rt_event_create("event",RT_IPC_FLAG_FIFO);
        修改代码
        Led1发送1<<5
        Led2发送1<<6
        Led3接收 1<<5 |1<<6
        Led3接收 1<<5 &1<<6
        static void led1_thread_entery(void* parameter)
        {
                rt_hw_led_init();//初始化io口
                while(1)
                {
                  rt_event_send(pEvent,1<<5);
                        //rt_sem_take(pSem,RT_WAITING_FOREVER);
                        rt_hw_led_on(1);
                        rt_thread_delay( RT_TICK_PER_SECOND);
                        rt_hw_led_off(1);
                        rt_thread_delay( RT_TICK_PER_SECOND );
                        //rt_sem_release(pSem);
               
                }
        }
       
        static void led2_thread_entery(void* parameter)
        {
                //rt_hw_led_init();//初始化io口
                while(1)
                {
                       rt_event_send(pEvent,1<<6);
                        //rt_sem_take(pSem,RT_WAITING_FOREVER);
                        rt_hw_led_on(2);
                        rt_thread_delay( RT_TICK_PER_SECOND);
                        rt_hw_led_off(2);
                        rt_thread_delay( RT_TICK_PER_SECOND );
                        //rt_sem_release(pSem);
                }
        }
       
        static void led3_thread_entery(void* parameter)
        {
                rt_uint32_t Temp;
                //rt_hw_led_init();//初始化io口
                while(1)
                {
                        rt_event_recv(pEvent,1<<5|1<<6,RT_EVENT_FLAG_OR,RT_WAITING_FOREVER,&Temp);
                        //rt_mutex_take(pMutex,RT_WAITING_FOREVER);
                        rt_hw_led_on(3);
                        rt_thread_delay( RT_TICK_PER_SECOND);
                        rt_hw_led_off(3);
                        rt_thread_delay( RT_TICK_PER_SECOND );
                        //rt_mutex_release(pMutex);
       
                }
        }
       
        static void led4_thread_entery(void* parameter)
        {
                //rt_hw_led_init();//初始化io口
                rt_uint32_t e;
                while(1)
                {
                        rt_event_recv(pEvent,1<<5|1<<6,RT_EVENT_FLAG_AND,RT_WAITING_FOREVER,&e);
                        //rt_mutex_take(pMutex,RT_WAITING_FOREVER);
                        rt_hw_led_on(4);
                        rt_thread_delay( RT_TICK_PER_SECOND);
       
                        rt_hw_led_off(4);
                        rt_thread_delay( RT_TICK_PER_SECOND );
                        //rt_mutex_release(pMutex);
                }
        }
       
        Led3,led4能够一闪一闪就说明收到事件了
        从finsh看
       \ | /
        - RT -   Thread Operating System
       / | \ 0.4.0 build Nov 13 2011
       2006 - 2011 Copyright by rt-thread team
        finsh>>list_event()
        event    set      suspend thread
        -------- ---------- --------------
        event   0x00000060 0
                0, 0x00000000
        finsh>>

lindabell 发表于 2011-11-13 14:57:30

4.3邮箱
        一个邮箱里可以放4个字节的数据(最好是指针了),同理
        static rt_mailbox_t pMailbox;        //邮箱
       
        pMailbox=rt_mb_create("mailbox",5,RT_IPC_FLAG_FIFO);
       
       
        static void led1_thread_entery(void* parameter)
        {
                rt_hw_led_init();//初始化io口
                while(1)
                {
                  rt_mb_send(pMailbox,0xAABBCCDD);//发送一个邮箱数据
                        rt_event_send(pEvent,1<<5);
                        //rt_sem_take(pSem,RT_WAITING_FOREVER);
                        rt_hw_led_on(1);
                        rt_thread_delay( RT_TICK_PER_SECOND);
                        rt_hw_led_off(1);
                        rt_thread_delay( RT_TICK_PER_SECOND );
                        //rt_sem_release(pSem);
               
                }
        }
       
        static void led2_thread_entery(void* parameter)
        {
                //rt_hw_led_init();//初始化io口
                rt_uint32_t temp=0;
                while(1)
                {
                        rt_mb_recv(pMailbox,&temp,RT_WAITING_FOREVER);
                        if(temp==0XAABBCCDD)
                        {
                                rt_event_send(pEvent,1<<6);
                                //rt_sem_take(pSem,RT_WAITING_FOREVER);
                                rt_hw_led_on(2);
                                rt_thread_delay( RT_TICK_PER_SECOND);
                                rt_hw_led_off(2);
                                rt_thread_delay( RT_TICK_PER_SECOND );
                                //rt_sem_release(pSem);
                        }
                       
                }
        }
       
        现象led2一闪一闪说明收到了正确的数据了
       
       \ | /
        - RT -   Thread Operating System
       / | \ 0.4.0 build Nov 13 2011
       2006 - 2011 Copyright by rt-thread team
        finsh>>list_mailbox()
        mailboxentry size suspend thread
        -------- -------- --------------
        mailbox00000005 0
                0, 0x00000000
        finsh>>
        finsh>>

lindabell 发表于 2011-11-13 15:02:28

队列,比较费资源。没有仔细看。就算了

binaimei2007 发表于 2011-11-13 15:20:48

谢谢楼主的分享,我也正在准备学习。

tiancaigao7 发表于 2011-11-13 15:41:54

楼上看得很快呀,相比之下我就慢了很多。刚刚弄到信号量那部分。感觉和ucos非常类似,如果有ucos的基础,这个概念基本上就不用看了,不过也可能因为太相似了,有一些函数的功能还是有区别的,这点对于有ucos基础的人反而是一个障碍。
楼主弄到了信号量部分,你创建的是一个FIFO模式的信号量,我想了解一下FIFO模式和优先级模式个什么区别?为自己做了一个例子实验了一下,发现并没有什么区别,都是优先级不同的话,最高优先级的任务获得信号量,优先级相同的,先申请信号量的任务获得信号量,这个不知道楼主研究过没有?

seaman117 发表于 2011-11-13 16:55:28

我移植到lpc1752上经常出现硬件异常,找原因中!

edaworld 发表于 2011-11-13 17:05:56

马甲

lixupeng 发表于 2011-11-13 17:52:02

mark

lindabell 发表于 2011-11-13 18:49:52

回复【13楼】tiancaigao7天才杨威利
-----------------------------------------------------------------------

我也没有什么ucos ii的经验了,只是上学时看过一遍而已。
   看看你是不是这种情况:
   假设A优先级比B的优先级高。
   1.但是B申请信号量时,A其实没有申请;那么信号量当然给B了。
   2.假如C已经占有信号量了,还没有释放;AB又同时申请该信号量了;那么在C释放了该信号量之后
   1)如果使用FIFO的话就给先申请的
   2)如果是基于优先级的则给A

soos 发表于 2011-11-13 18:55:38

楼主一定要继出下部,支持.

tiancaigao7 发表于 2011-11-13 19:16:48

回复【17楼】lindabell 欧海
回复【13楼】tiancaigao7天才杨威利
-----------------------------------------------------------------------
我也没有什么ucos ii的经验了,只是上学时看过一遍而已。
   看看你是不是这种情况:
   假设a优先级比b的优先级高。
   1.但是b申请信号量时,a其实没有申请;那么信号量当然给b了。
   2.假如c已经占有信号量了,还没有释放;ab又同时申请该信号量了;那么在c释放了该信号量之后
   1)如果使用fifo的话就给先申请的
   2)如果是基于优先级的则给a

-----------------------------------------------------------------------

回复楼主,我实验室这样进行的,信号量FIFO模式下,AB两个任务中分别申请信号量,AB两个任务优先级相同,任务C发送信号量(一次)。在启动任务的时候,按照顺序启动任务A B,之后在启动任务C(任务C启动的时候,任务AB都因为没有信号量而挂起)。分别在任务AB中获取信号量函数后面设定断点。发现这种情况下A任务进入断点。如果我在创建让任务的时候让B任务优先级比A任务高,那么会进入到B任务的断点中。当然在PRIO模式下也是一样。不知道楼主是否遇到过这方面的问题。
另外,我现在似乎用的是3.3.0版,听说4.0版的RTT中不再有start_rvds.s这个启动文件,而是直接利用STM32对应的启动文件,是不是这样?打算下载一个4.0版看看,不知道是否稳定。

lindabell 发表于 2011-11-13 21:51:47

回复【19楼】tiancaigao7天才杨威利
-----------------------------------------------------------------------
“任务C发送信号量(一次)”信号量能发送吗??

贴一下我的代码
线程入口
static void led1_thread_entery(void* parameter)
{
        rt_device_t Wrdevice;
        rt_hw_led_init();//初始化io口
       Wrdevice=rt_device_find("uart1");
        rt_device_open(Wrdevice,RT_DEVICE_FLAG_DMA_TX);
        while(1)
        {
          // rt_device_write(Wrdevice,0,Str,sizeof(Str)-1);
        //        rt_mb_send(pMailbox,0xAABBCCDD);//发送一个邮箱数据
        //        rt_event_send(pEvent,1<<5);
                rt_thread_delay( RT_TICK_PER_SECOND/2);
                rt_sem_take(pSem,RT_WAITING_FOREVER);
                rt_kprintf("led1\r\n");
                rt_hw_led_on(1);
                rt_thread_delay( RT_TICK_PER_SECOND);
                rt_hw_led_off(1);
                rt_thread_delay( RT_TICK_PER_SECOND );
                rt_sem_release(pSem);
       
        }
}

static void led2_thread_entery(void* parameter)
{
        //rt_hw_led_init();//初始化io口
        rt_uint32_t temp=0;
        while(1)
        {
                //rt_mb_recv(pMailbox,&temp,RT_WAITING_FOREVER);
                //if(temp==0XAABBCCDD)
                //{
                        //rt_event_send(pEvent,1<<6);
                        rt_thread_delay( RT_TICK_PER_SECOND);
                        rt_sem_take(pSem,RT_WAITING_FOREVER);
                        rt_kprintf("led2\r\n");
                        rt_hw_led_on(2);
                        rt_thread_delay( RT_TICK_PER_SECOND);
                        rt_hw_led_off(2);
                        rt_thread_delay( RT_TICK_PER_SECOND );
                        rt_sem_release(pSem);
                //}
               
        }
}

static void led3_thread_entery(void* parameter)
{
        rt_uint32_t Temp;
        //rt_hw_led_init();//初始化io口
        while(1)
        {
                //rt_event_recv(pEvent,1<<5|1<<6,RT_EVENT_FLAG_OR,RT_WAITING_FOREVER,&Temp);
                //rt_mutex_take(pMutex,RT_WAITING_FOREVER);
                rt_sem_take(pSem,RT_WAITING_FOREVER);
                rt_kprintf("led3\r\n");
                rt_hw_led_on(3);
                rt_thread_delay( 5*RT_TICK_PER_SECOND);
                rt_hw_led_off(3);
                rt_thread_delay(5* RT_TICK_PER_SECOND );
                //rt_mutex_release(pMutex);
                rt_sem_release(pSem);

        }
}

创建线程
void rt_led_init(void)
{
        rt_thread_t led_tid;
       
        pSem=rt_sem_create("sem",1,RT_IPC_FLAG_PRIO);
        pMutex=rt_mutex_create("mutex",RT_IPC_FLAG_FIFO);
        pEvent=rt_event_create("event",RT_IPC_FLAG_FIFO);
        pMailbox=rt_mb_create("mailbox",5,RT_IPC_FLAG_FIFO);
               
        led_tid=rt_thread_create("led1",
                                                        led1_thread_entery,RT_NULL,
                                                        2000,30,5
                                                        );
        if(led_tid!=RT_NULL) rt_thread_startup(led_tid);
       
        led_tid=rt_thread_create("led2",
                                                        led2_thread_entery,RT_NULL,
                                                        2000,29,5
                                                        );
        if(led_tid!=RT_NULL) rt_thread_startup(led_tid);
       
        led_tid=rt_thread_create("led3",
                                                        led3_thread_entery,RT_NULL,
                                                        2000,28,5
                                                        );
        if(led_tid!=RT_NULL) rt_thread_startup(led_tid);
       
        led_tid=rt_thread_create("led4",
                                                        led4_thread_entery,RT_NULL,
                                                        2000,27,5
                                                        );
        if(led_tid!=RT_NULL) rt_thread_startup(led_tid);
}

当基于FIFo时led3->led2->led1
基于优先级时led3->led2->led3->led2

SNOOKER 发表于 2011-11-13 23:20:46

唉,就是对LM3S的的支持太弱了

changhui0222 发表于 2011-11-14 00:08:37

不错。mark!

3050311118 发表于 2011-11-14 08:47:03

楼主写得不错

lindabell 发表于 2011-11-14 09:13:28

RTT的IO设备复杂的,看了2遍没怎么看懂

yinglively 发表于 2011-11-14 10:28:36

关注中

wisology 发表于 2011-11-14 11:23:09

mark...

lindabell 发表于 2011-11-14 17:51:09

今天弄了SRAM
参见http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=5197842&bbs_page_no=1&search_mode=3&search_text=lindabell&bbs_id=9999

在board.h中修改成(我的SRAM是1M的)
/* whether use board external SRAM memory */
// <e>Use external SRAM memory on the board
//         <i>Enable External SRAM memory
#define STM32_EXT_SRAM          1
//        <o>Begin Address of External SRAM
//                <i>Default: 0x68000000
#define STM32_EXT_SRAM_BEGIN    0x68000000 /* the begining address of external SRAM */
//        <o>End Address of External SRAM
//                <i>Default: 0x68080000
#define STM32_EXT_SRAM_END      0x68100000 /* the end address of external SRAM */

为了看出动态分配的情况在rtdebug.h中
/* Turn on some of these (set to non-zero) to debug kernel */
#ifndef RT_DEBUG_MEM
#define RT_DEBUG_MEM      0
#endif
改成
/* Turn on some of these (set to non-zero) to debug kernel */
#ifndef RT_DEBUG_MEM
#define RT_DEBUG_MEM      1
#endif

初始化FSMC,在board.c中修改EXT_SRAM_Configuration使符合你的板子,下面是我的
void EXT_SRAM_Configuration(void)
{

                  FSMC_NORSRAMInitTypeDefFSMC_NORSRAMInitStructure;
                FSMC_NORSRAMTimingInitTypeDefp;
                GPIO_InitTypeDef GPIO_InitStructure;
   
    {

      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOF
                               | RCC_APB2Periph_GPIOG, ENABLE);
      RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);

      GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

               /*
      FSMC_D0 ~ FSMC_D3
      PD14         FSMC_D0   
                PD15         FSMC_D1
                PD0        FSMC_D2   
                PD1        FSMC_D3
      */
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_14 | GPIO_Pin_15;
      GPIO_Init(GPIOD,&GPIO_InitStructure);

      /*
      FSMC_D4 ~ FSMC_D12
      PE7 ~ PE15FSMC_D4 ~ FSMC_D12
      */
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10
                                    | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
      GPIO_Init(GPIOE,&GPIO_InitStructure);

      /* FSMC_D13 ~ FSMC_D15   PD8 ~ PD10 */
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
      GPIO_Init(GPIOD,&GPIO_InitStructure);

      /*
      FSMC_A0 ~ FSMC_A5   FSMC_A6 ~ FSMC_A9
      PF0   ~ PF5       PF12    ~ PF15
      */
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3
                                    | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
      GPIO_Init(GPIOF,&GPIO_InitStructure);

      /* FSMC_A10 ~ FSMC_A15
                   PG0      ~ PG5 */
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
      GPIO_Init(GPIOG,&GPIO_InitStructure);

      /* FSMC_A16 ~ FSMC_A18
                   PD11   ~ PD13 */
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
      GPIO_Init(GPIOD,&GPIO_InitStructure);

                /*FSMC_A19 ~ FSMC_A21
                   PE3      ~ PE6          */
               GPIO_InitStructure.GPIO_Pin =GPIO_Pin_3 | GPIO_Pin_4|GPIO_Pin_5 | GPIO_Pin_6;
               GPIO_Init(GPIOE,&GPIO_InitStructure);

      /* RD-PD4
                   WR-PD5 */
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
      GPIO_Init(GPIOD,&GPIO_InitStructure);

      /* NBL0-PE0
                   NBL1-PE1 */
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
      GPIO_Init(GPIOE,&GPIO_InitStructure);

               
//      /* NE1/NCE2 */
//      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;       ///????????????????????????????/
//      GPIO_Init(GPIOD,&GPIO_InitStructure);
//      /* NE2 */
//      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
//      GPIO_Init(GPIOG,&GPIO_InitStructure);
      /* NE3 */
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
      GPIO_Init(GPIOG,&GPIO_InitStructure);
      /* NE4 */
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
      GPIO_Init(GPIOG,&GPIO_InitStructure);
    }
    /* FSMC GPIO configure */

        /*-- FSMC Configuration ------------------------------------------------------*/
        p.FSMC_AddressSetupTime = 0;
        p.FSMC_AddressHoldTime = 0;
        p.FSMC_DataSetupTime = 2;
        p.FSMC_BusTurnAroundDuration = 0;
        p.FSMC_CLKDivision = 0;
        p.FSMC_DataLatency = 0;
        p.FSMC_AccessMode = FSMC_AccessMode_A;

        FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3;
        FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
        FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
        FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
//        FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
        FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
        FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
        FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
        FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
    FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
        FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
        FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
        FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
        FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
        FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;


        FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);

        /* Enable FSMC Bank1_SRAM Bank */
        FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE);
}

从finsh看看,有什么变化


\ | /
- RT -   Thread Operating System
/ | \ 0.4.0 build Nov 14 2011
2006 - 2011 Copyright by rt-thread team
mem init, heap begin address 0x68000000, size 1048552
malloc size 152
allocate memory at 0x6800000c, size: 164
malloc size 2048
allocate memory at 0x680000b0, size: 2060
malloc size 696
allocate memory at 0x680008bc, size: 708
malloc size 44
allocate memory at 0x68000b80, size: 56
malloc size 48
allocate memory at 0x68000bb8, size: 60
malloc size 44
allocate memory at 0x68000bf4, size: 56
malloc size 60
allocate memory at 0x68000c2c, size: 72
malloc size 20
allocate memory at 0x68000c74, size: 32
malloc size 152
allocate memory at 0x68000c94, size: 164
malloc size 2000
allocate memory at 0x68000d38, size: 2012
malloc size 152
allocate memory at 0x68001514, size: 164
malloc size 2000
allocate memory at 0x680015b8, size: 2012
malloc size 152
allocate memory at 0x68001d94, size: 164
malloc size 2000
allocate memory at 0x68001e38, size: 2012
malloc size 152
allocate memory at 0x68002614, size: 164
malloc size 2000
allocate memory at 0x680026b8, size: 2012
finsh>>led3

release memory 0x680000b0, size: 2060
release memory 0x6800000c, size: 164

lindabell 发表于 2011-11-16 11:09:15

RTT的IO设备居然这么复杂,总是理不清思路

chewy 发表于 2011-11-16 15:58:25

回复【2楼】lindabell欧海
1.2怎么映finsh射到串口2呢(我的串口1需要他用)
参见http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=5191294&bbs_page_no=1&search_mode=3&search_text=lindabell&bbs_id=9999
在board.c修改如下
// <o> console on usart: <0=> no console <1=>usart 1 <2=>usart 2 <3=> usart 3
//         <i>default: 1
#define stm32_console_usart       2    //原来是1
在rtconfig.c修改如下
/* section: device system */......
-----------------------------------------------------------------------

貌似这里你提到的board.c和rtconfig.c在0.40RC1中应该是board.h和startup.c
郁闷了。。。。

lindabell 发表于 2011-11-16 16:25:20

回复【29楼】chewy
-----------------------------------------------------------------------
更正这些配置分别在下面3个文件中(看来真的累了)
board.h
rtconfig.h
startup.c

chewy 发表于 2011-11-16 16:49:48

回复【30楼】lindabell欧海

回复【29楼】chewy
-----------------------------------------------------------------------
更正这些配置分别在下面3个文件中(看来真的累了)
board.h
rtconfig.h
startup.c

-----------------------------------------------------------------------
呵呵 直接把你帖子里的改了吧 不然有人会跟错~

lindabell 发表于 2011-11-16 16:54:48

回复【31楼】chewy
-----------------------------------------------------------------------
我也想改啊,你不知道贴发出24小时就不能改了吗
http://cache.amobbs.com/bbs_upload782111/files_47/ourdev_695807XO5TIY.png
(原文件名:err.png)

chewy 发表于 2011-11-16 17:09:33

回复【32楼】lindabell欧海
-----------------------------------------------------------------------

额 还真不知道。。。囧

lindabell 发表于 2011-11-17 17:23:59

IO 设备
弄了3天的时间,现在感觉才明白一点
1.初始化硬件
2.注_册到RTT
3.查找io设备
4.调用io设备的相关函数

感觉还是表达不清楚,直接上文件
点击此处下载 ourdev_696154PZJAVT.rar(文件大小:2K) (原文件名:USART1.rar)

flyingcys 发表于 2011-11-17 18:48:41

关注!

cnsxgh 发表于 2011-11-18 16:31:47

非常感谢楼主的分享!我正在寻找像你这样的帖子!

arm7tdmi 发表于 2011-11-22 11:48:58

楼主是个好人.........

tiancaigao7 发表于 2011-11-24 19:44:48

回复【28楼】lindabell 欧海
rtt的io设备居然这么复杂,总是理不清思路
-----------------------------------------------------------------------

确实 RTT的IO设备感觉太复杂了,不过很大程度上是因为RTT的编程指南写的不清楚,也不太专业。很多应该说的话没有说到。IO设备部分是后面使用GUI,FS LWIP等等外设的基础,因此虽然现在我不太明白,但是也要保证大体上知道如何修改。
另外不知道楼主是不是发现了,RTT的线程完成同样的任务要比ucos多占用很多线程栈?而且使用它内置的文件系统的代码要比我移植FATFS大很多,因此现在我还是用RTT+FATFS来做的。

wangwj 发表于 2011-11-25 10:42:16

good!!!!!!!

wangwj 发表于 2011-11-25 11:00:03

楼主用的自己的开发板?

thevip 发表于 2011-11-30 21:42:33

感谢楼主的分享!

lindabell 发表于 2011-12-1 17:02:58

回复【38楼】tiancaigao7天才杨威利
-----------------------------------------------------------------------

这个倒是不清楚

补充;打错字

wuguoyan 发表于 2011-12-1 17:16:42

好东西,顶下,支持下,要是能出个PDF版本的就更好了,谢谢楼主

w1000 发表于 2011-12-2 17:33:41

学习学习了。

fgcx 发表于 2011-12-3 00:08:45

我的串口回去怎么输出乱码,用串口助手。

Asch 发表于 2011-12-7 19:37:55

我现在还没入门,随便看看

wangzheyu 发表于 2011-12-7 20:59:25

mark

ifatal 发表于 2011-12-8 01:21:06

支持lz继续下去

cnsxgh 发表于 2011-12-12 09:57:12

回复【8楼】lindabell欧海
-----------------------------------------------------------------------

我现在每天都在学习楼主的教程。现在学到了信号量,
写了如下代码:
static rt_sem_t pSem=RT_NULL; //信号量
pSem=rt_sem_create("sem",1,RT_IPC_FLAG_FIFO);


static void rt_thread_entry_led1(void* parameter)
{
    /* init led configuration */
    rt_hw_led_init();

    while (1)
    {
            rt_sem_take(pSem,RT_WAITING_FOREVER);
      /* led on */
      rt_kprintf("led1 on\r\n");
      rt_hw_led_on(0);
      rt_thread_delay(50); /* sleep 0.5 second and switch to other thread */

      /* led off */
      rt_kprintf("led1 off\r\n");
      rt_hw_led_off(0);
      rt_thread_delay(50);
                rt_sem_release(pSem);
    }
}
结果,编译不通过:
application.c(168): error:#77-D: this declaration has no storage class or type specifier
请问是啥原因?

gshuang1 发表于 2011-12-14 23:20:22

回复【4楼】tyqhaha
最近在看ucos,不过rtt最近听到好多人在说 呵呵
-----------------------------------------------------------------------

ucos这种东西不算什么操作系统,它不支持多线程,实时性不高。

lindabell 发表于 2011-12-15 20:58:38

回复【49楼】cnsxgh
-----------------------------------------------------------------------

提示说你这里没有存储类型,是不是忘记int 、char什么的了

pswarfound 发表于 2011-12-21 21:01:05

向楼主学习,可怜我还在等待审核,不能请教各位了

hybbb 发表于 2012-1-6 10:46:36

楼主太有才了,对我等初哥帮助很大,期待精彩下文

163fit 发表于 2012-10-30 20:39:16

楼主能否描述一上用一个邮箱方式来通知 线程上的调用.

STM32LOU 发表于 2013-4-4 19:59:02

学习了。。。

hunxiyi 发表于 2013-4-15 16:44:31

顶一个!!!!现在开始学习,先MARK
页: [1]
查看完整版本: 学习RT-thread记录