打印
[程序源码]

你把UML用在mcu或者linux开发上面了吗?

[复制链接]
楼主: keer_zu
手机看帖
扫描二维码
随时随地手机跟帖
41
keer_zu|  楼主 | 2014-5-11 18:28 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
b.索引功能函数
static int esl_cmd_build(short id,char cmd,const char *para,unsigned int para_len,char *frame,unsigned int *frame_len)
{
        int ret;
        struct esl_protocol *proto;
        struct func_node *fnode;
       
       
        proto = &g_esl_proto;


        fnode = proto->fun_h->get_func_node(proto->fun_h,cmd);
        if(fnode == NULL){
                printf("func:%s()  cmd build func node get err!\n",__FUNCTION__);
                return ERR;
        }


        ret = ((CMD_BUILD_T)fnode->param)(id,cmd,para,para_len,frame,frame_len);
        if(ret != OK){
                printf("func:%s()  cmd build err!\n",__FUNCTION__);
                return ERR;
        }

        _DBG("++++++ %s:%d \n",__FUNCTION__,__LINE__);
       
        return OK;
}

使用特权

评论回复
42
keer_zu|  楼主 | 2014-5-11 18:29 | 只看该作者
c.哈希节点定义:
func_node_t esl_cmd_func_node_array_can[] =
{
        {CMD_SYS_RESET,system_reset_can,{NULL,NULL}},
        {CMD_MODIFY_ADDR,modify_addr_can,{NULL,NULL}},
        {CMD_UPDATE_DISPLAY,update_display_can,{NULL,NULL}},
        {CMD_LCD_GET_ITEM,lcd_get_item_can,{NULL,NULL}},
        {CMD_CODE_SCAN,get_scan_code_can,{NULL,NULL}},
        {CMD_LED_CONTROL,led_gr_control_can,{NULL,NULL}},
        {CMD_SCAN_SWITCH,scan_switch_can,{NULL,NULL}},
//        {'z',cmd_Z_process,{NULL,NULL}},
        {0,NULL,{NULL,NULL}}
};

使用特权

评论回复
43
keer_zu|  楼主 | 2014-5-12 09:54 | 只看该作者
继续开始一个人的帖子。有感兴趣的关注一下。

使用特权

评论回复
44
keer_zu|  楼主 | 2014-5-12 09:59 | 只看该作者
linux内核中充满了面向对象的思想,mod本身就体现了面向对象的思想,所有的驱动程序或者其他内核功能都可以模块的形式被‘打入’(加载insmod)内核。模块的加载、卸载、接口的定义等等,无不体现面向对象的思想。

使用特权

评论回复
45
keer_zu|  楼主 | 2014-5-12 10:05 | 只看该作者
同样是C语言的应用,基于有限资源环境下的嵌入式应用完全可以通过UML对系统进行建模(不要说你不会就排斥它,都是学出来的,当年用惯汇编的人,觉得C也看不懂,转过来就不想再回去了/极个别除外,linus开始也用汇编,当天开始转向C的时候,他惊叹效率之高,当然他排斥C++或许有一定道理)

使用特权

评论回复
46
keer_zu|  楼主 | 2014-5-12 10:10 | 只看该作者
用结构体去实现一个类是很轻而易举的事情,在此基础上实现类的关联也非难事。当然继承有点繁琐,记得《设计模式》的作者也建议少用继承,不过用继承实现接口类还是很有用的。
基于面向对象的设计方法,今天已经很成熟了。它没有必要和面向对象的设计语言绑定,其实用汇编也可以实现面向对象的设计,只是麻烦些而已,设计思想就是设计思想,不要将他等同为语言,这往往是我们初接触者的认知误区。

使用特权

评论回复
47
keer_zu|  楼主 | 2014-5-12 10:14 | 只看该作者
至于怎么从需求分析中得到系统的类结构,这个目前还没有软件能自动做到,你筛选出来的类,以及类与类之间的关系是否更完美,完全看你对面向对象的理解,以及你对系统本身的理解,以及你拥有的设计经验,这个是长期实践总结的结果,所以一个优秀的嵌入式架构师是很难得的。

使用特权

评论回复
48
keer_zu|  楼主 | 2014-5-12 10:17 | 只看该作者
当你真正开始买入这个门槛后,你一定再也不想回到过去堆砌代码的时代,如果你能随心所欲使用‘设计模式’,你将体会到这样做的好处,你将乐此不疲。。。。
记住,这才是你做为代码工作者的目标:你是一位设计人员,你是一位工程师,而不是代码的堆砌者,你不是一位‘匠人’。

使用特权

评论回复
49
keer_zu|  楼主 | 2014-5-12 10:26 | 只看该作者
做到这一点,对程序员的要求是:
1.深入理解面向对象。
2.对指针的熟练使用。

使用特权

评论回复
50
keer_zu|  楼主 | 2014-5-12 11:27 | 只看该作者
本帖最后由 keer_zu 于 2014-5-12 11:34 编辑

最近一个项目,处理CAN收发的一个线程:

这个是主从结构中,主设备的程序,为了接收处理不同地址从设备发过来的分包数据,将接收缓冲区做成哈希结构,通过地址索引之前收到的同一地址的数据,等收到末尾分包后,完成整帧数据接收并处理之。。。。。分包数据存在每个哈希节点下的双链表里面。

处理完毕后,将缓冲区片还回空闲缓冲区队列。如果收到新的分包,将会从空闲缓冲区片队列中取出一片,填上数据,初始化链表项,插入相关链表中。


对于帧不完整的,做超时处理。
测试结果:系统平稳。
static int can_thread_func(void *para)
{
        int ret,i;
        struct can_comx *can;
        struct can_frame frame;
        unsigned char *buf;
        unsigned short addr;
        unsigned char dir;
        unsigned char attr;
        unsigned char index;
        unsigned char ack;
        struct can_frame_list *pos = NULL,*can_frame = NULL;
        struct list_head  *pos_h;
        unsigned char flag = 0;
        struct aioi_proto *proto;
        proto = &g_aioi_proto;
        struct return_data *ret_d;
        unsigned char *node_buf;

        can_data_t ack_update;
        unsigned char ack_data[10];


        struct recv_packet_node *packet_node;
        struct recv_hlist_head *h_head;
        struct recv_h_node *h_node;


        
        can = (struct can_comx *)para;

        memset(ack_data,0,10);
        
        while(1){
                ret = can->can.recv(&can->can,&frame);
               
                if(ret < 0){
                        printf("############### can frame recv err!\n");
                        can->is_thread_alive == 0;
                        return ERR;
                }

                if(ret == 0){
                        usleep(100);
                        continue;
                }
                addr = _id_get_addr(frame.can_id);
                attr = _id_get_attr(frame.can_id);
                ack = _id_get_ack(frame.can_id);
                index = _id_get_index(frame.can_id);
                dir = _id_get_dir(frame.can_id);

                if(dir != 0x01)
                        continue;
               
                flag = 0;


                if(ack == 1){
                        h_head = can->recv_head_array_ack + DATA_MOD(addr,H_HEAD_ARRY_SIZE);
                        h_node = recv_hlist_get(h_head,addr);
                        if(h_node != NULL){
                                flag = 1;
                        }
                }else if(ack == 0){
                        h_head = can->recv_head_array_req + DATA_MOD(addr,H_HEAD_ARRY_SIZE);
                        h_node = recv_hlist_get(h_head,addr);
                        if(h_node != NULL){
                                flag = 1;
                        }
                }else{
                        printf("!!! wrong ack!\n");
                }
               
               
                if(flag == 0 && attr == 0){
                        if(ack == 1){
                                buf = get_free_para_buf(can->answer_q);
                                if(buf != NULL){
                                        memset(buf,0,PARA_BUF_SIZE);
                                        *(unsigned short *)buf = addr;
                                        buf[2] += frame.can_dlc;
                                        memcpy(buf + 3,frame.data,frame.can_dlc);

                                        ret = para_process_buf_insert(can->answer_q);
                                        if(ret != OK){
                                                printf("###############  Can ack q insert err! line:%d\n",__LINE__);
                                                return ret;
                                        }
                                }
                        }else{
                                buf = get_free_para_buf(proto->para_buf_q);
                                if(buf != NULL){
                                        memset(buf,0,PARA_BUF_SIZE);
                                        ret_d = (struct return_data *)buf;
                                        ret_d->type = frame.data[0];//DATA_TYPE_DISP;
                                        ret_d->len = frame.can_dlc;
                                        ret_d->id = addr;
                                       
                                        memcpy(buf + sizeof(struct return_data),frame.data + 1,ret_d->len - 1);
                                       
                                        ret = para_process_buf_insert(proto->para_buf_q);
                                        if(ret != OK){
                                                printf("############### Can update q insert err! line:%d\n",__LINE__);
                                                return ret;
                                        }
                                       
                                        ack_update.id = _create_can_id(0,addr,0,0,0,1);
                                        ack_data[0] = 0x80 + 0x32;
                                        ack_data[1] = 'o';
                                        ack_update.data = ack_data;
                                        ack_update.can_dlc = 2;

                                        ret = can->can.send(&can->can,&ack_update);
                                        if(ret != OK){
                                                printf("############### can send err!\n");
                                                return ERR;
                                        }
                                }
                        }

                }else if(flag == 0 && attr == 1){
_get_recv_h_node1:
                        h_node = (struct recv_h_node *)get_q_buf(can->h_elem_q);
                        if(h_node == NULL){
                                usleep(100);
                                goto _get_recv_h_node1;
                        }

                        h_node->ack = ack;
                        h_node->addr = addr;
                        gettimeofday(&h_node->tv_now,NULL);
                        INIT_LIST_HEAD(&h_node->packet_head);
_get_recv_packet_node1:
                        packet_node = (struct recv_packet_node *)get_q_buf(can->packet_elem_q);
                        if(packet_node == NULL){
                                usleep(100);
                                goto _get_recv_packet_node1;
                        }

                        packet_node->dlc = frame.can_dlc;
                        packet_node->index = index;
                        memcpy(packet_node->data,frame.data,packet_node->dlc);

                        list_add_tail(&packet_node->pack_list,&h_node->packet_head);
                        
                        if(ack == 1)
                                recv_hlist_add(can->recv_head_array_ack,h_node);
                        else
                                recv_hlist_add(can->recv_head_array_req,h_node);

                }else if(flag == 1 && attr == 0){
_get_recv_packet_node2:
                        packet_node = (struct recv_packet_node *)get_q_buf(can->packet_elem_q);
                        if(packet_node == NULL){
                                usleep(100);
                                goto _get_recv_packet_node2;
                        }

                        packet_node->dlc = frame.can_dlc;
                        packet_node->index = index;
                        memcpy(packet_node->data,frame.data,packet_node->dlc);

                        list_add_tail(&packet_node->pack_list,&h_node->packet_head);

                        if(ack == 1){
                                buf = get_free_para_buf(can->answer_q);
                                if(buf != NULL){
                                        *(unsigned short *)buf = h_node->addr;
                                        buf[2] = 0;
                                        list_for_each(pos_h,&h_node->packet_head){
                                                packet_node = list_entry(pos_h,struct recv_packet_node,pack_list);
                                                memcpy(buf + 3 + buf[2],packet_node->data,packet_node->dlc);
                                                buf[2] += packet_node->dlc;

                                                __list_del(packet_node->pack_list.prev,packet_node->pack_list.next);

                                                q_buf_insert(can->packet_elem_q,(unsigned char *)packet_node);
                                        }
                                        hlist_del(&h_node->node);
                                        q_buf_insert(can->h_elem_q,(unsigned char*)h_node);
                                       
                                        para_process_buf_insert(can->answer_q);
                                }
                        }else{
                                        buf = get_free_para_buf(proto->para_buf_q);
                                        if(buf != NULL){
                                                ret_d = (struct return_data *)buf;
                                                ret_d->len = 0;
                                                list_for_each(pos_h,&h_node->packet_head){
                                                        packet_node = list_entry(pos_h,struct recv_packet_node,pack_list);
                                                        memcpy(buf + sizeof(struct return_data) + ret_d->len,packet_node->data,packet_node->dlc);
                                                        ret_d->len += packet_node->dlc;

                                                        __list_del(packet_node->pack_list.prev,packet_node->pack_list.next);
                                                        
                                                        q_buf_insert(can->packet_elem_q,(unsigned char *)packet_node);
                                                }

                                                ret_d->type = (char)(*(buf + sizeof(struct return_data)));
                                                ret_d->id = addr;
                                                hlist_del(&h_node->node);
                                                q_buf_insert(can->h_elem_q,(unsigned char*)h_node);

                                                para_process_buf_insert(proto->para_buf_q);
                                        }
                        }

                }else if(flag == 1 && attr == 1){

_get_recv_packet_node3:
                        packet_node = (struct recv_packet_node *)get_q_buf(can->packet_elem_q);
                        if(packet_node == NULL){
                                usleep(100);
                                goto _get_recv_packet_node3;
                        }

                        packet_node->dlc = frame.can_dlc;
                        packet_node->index = index;
                        memcpy(packet_node->data,frame.data,packet_node->dlc);

                        list_add_tail(&packet_node->pack_list,&h_node->packet_head);

                        gettimeofday(&h_node->tv_now,NULL);
                }
        
                if(can->is_thread_alive == 0)
                        return OK;
                usleep(10);
        }
        return OK;
}

使用特权

评论回复
51
keer_zu|  楼主 | 2014-5-12 12:41 | 只看该作者
以下摘自《设计模式》

什么是设计模式
Christopher Alexander 说过:“每一个模式描述了一个在我们周围不断重复发生的问题,
以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必做重复劳动”
[ A I S + 7 7,第1 0页]。尽管A l e x a n d e r所指的是城市和建筑模式,但他的思想也同样适用于面向
对象设计模式,只是在面向对象的解决方案里,我们用对象和接口代替了墙壁和门窗。两类
模式的核心都在于提供了相关问题的解决方案。
一般而言,一个模式有四个基本要素:
1. 模式名称(pattern name) 一个助记名,它用一两个词来描述模式的问题、解决方案
和效果。命名一个新的模式增加了我们的设计词汇。设计模式允许我们在较高的抽象层次上
进行设计。基于一个模式词汇表,我们自己以及同事之间就可以讨论模式并在编写文档时使
用它们。模式名可以帮助我们思考,便于我们与其他人交流设计思想及设计结果。找到恰当
的模式名也是我们设计模式编目工作的难点之一。
2. 问题(problem) 描述了应该在何时使用模式。它解释了设计问题和问题存在的前因后
果,它可能描述了特定的设计问题,如怎样用对象表示算法等。也可能描述了导致不灵活设
计的类或对象结构。有时候,问题部分会包括使用模式必须满足的一系列先决条件。
3. 解决方案(solution) 描述了设计的组成成分,它们之间的相互关系及各自的职责和协
作方式。因为模式就像一个模板,可应用于多种不同场合,所以解决方案并不描述一个特定
而具体的设计或实现,而是提供设计问题的抽象描述和怎样用一个具有一般意义的元素组合
(类或对象组合)来解决这个问题。
4. 效果(consequences) 描述了模式应用的效果及使用模式应权衡的问题。尽管我们描述
设计决策时,并不总提到模式效果,但它们对于评价设计选择和理解使用模式的代价及好处
具有重要意义。软件效果大多关注对时间和空间的衡量,它们也表述了语言和实现问题。因
为复用是面向对象设计的要素之一,所以模式效果包括它对系统的灵活性、扩充性或可移植
性的影响,显式地列出这些效果对理解和评价这些模式很有帮助。
出发点的不同会产生对什么是模式和什么不是模式的理解不同。一个人的模式对另一个
人来说可能只是基本构造部件。本书中我们将在一定的抽象层次上讨论模式。《设计模式》并
不描述链表和h a s h表那样的设计,尽管它们可以用类来封装,也可复用;也不包括那些复杂
的、特定领域内的对整个应用或子系统的设计。本书中的设计模式是对被用来在特定场景下
解决一般设计问题的类和相互通信的对象的描述。

使用特权

评论回复
52
keer_zu|  楼主 | 2014-5-12 13:01 | 只看该作者



将list.h用于 MSP430

使用特权

评论回复
53
keer_zu|  楼主 | 2014-5-12 13:08 | 只看该作者


有好几个之前430和stm使用过的类被应用与A8处理器下的linux项目 --- 一个上行为TCP协议,下行为CAN的控制器。

list.jpg (325.81 KB )

list.jpg

使用特权

评论回复
54
原野之狼| | 2014-5-12 13:48 | 只看该作者
曲高和寡啊

使用特权

评论回复
55
keer_zu|  楼主 | 2014-5-12 14:01 | 只看该作者
原野之狼 发表于 2014-5-12 13:48
曲高和寡啊

呵呵,我身边已经有几个被我拉下水了,正在学用rational rose或者Vp等UML建模工具。

使用特权

评论回复
56
grasswolfs| | 2014-5-12 14:56 | 只看该作者
阳春白雪不如泥腿子用的顺手~

使用特权

评论回复
57
keer_zu|  楼主 | 2014-5-12 15:46 | 只看该作者
grasswolfs 发表于 2014-5-12 14:56
阳春白雪不如泥腿子用的顺手~

踩单车很顺手 还要考驾*干嘛? 软件工程方法一直有人在尝试改进,为什么?当你真正掌握了,当你有了积累,你就知道什么才是真的顺手。

使用特权

评论回复
58
原野之狼| | 2014-5-12 17:01 | 只看该作者
楼主可以在论坛发起一个小项目  用设计模式、敏捷开发、UML那套东西带领大家一块玩一下  要不然大部分来看这帖子的不过是看看热闹罢了

使用特权

评论回复
59
keer_zu|  楼主 | 2014-5-12 17:22 | 只看该作者
原野之狼 发表于 2014-5-12 17:01
楼主可以在论坛发起一个小项目  用设计模式、敏捷开发、UML那套东西带领大家一块玩一下  要不然大部分来看 ...

是个好主意,不过现在项目很紧,这个稍后吧。先把之前的项目整理一下,很多方法是参考别人的,有些也是摸索的。我先整理个大概先。

使用特权

评论回复
60
grasswolfs| | 2014-5-12 17:52 | 只看该作者
keer_zu 发表于 2014-5-12 15:46
踩单车很顺手 还要考驾*干嘛? 软件工程方法一直有人在尝试改进,为什么?当你真正掌握了,当你有了积累 ...

汽车驾*顺手,航天飞机驾*我就不考了~

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则