Giter Site home page Giter Site logo

rt-thread / rt-thread Goto Github PK

View Code? Open in Web Editor NEW
9.6K 529.0 4.8K 817.91 MB

RT-Thread is an open source IoT real-time operating system (RTOS).

Home Page: https://www.rt-thread.io

License: Apache License 2.0

Shell 0.03% C 97.33% Assembly 1.86% Python 0.32% C++ 0.05% Logos 0.01% Makefile 0.02% HTML 0.36% CMake 0.01% Perl 0.01% CSS 0.01% Batchfile 0.01% Pawn 0.01% GDB 0.01% M4 0.01% RPC 0.01% Lex 0.01% Yacc 0.01% Tcl 0.01% Lua 0.01%
embedded-systems kernel iot rtos arm cortex-m cortex-a risc-v mips microcontroller

rt-thread's Introduction

English | 中文 | Español | Deutsch

GitHubStars GiteeStars GitHub GitHub release Gitter GitHub pull-requests PRs Welcome

RT-Thread

RT-Thread was born in 2006, it is an open source, neutral, and community-based real-time operating system (RTOS).

RT-Thread is mainly written in C language, easy to understand and easy to port(can be quickly port to a wide range of mainstream MCUs and module chips). It applies object-oriented programming methods to real-time system design, making the code elegant, structured, modular, and very tailorable.

RT-Thread has Standard version and Nano version. For resource-constrained microcontroller (MCU) systems, the Nano version that requires only 3KB Flash and 1.2KB RAM memory resources can be tailored with easy-to-use tools. For resource-rich IoT devices, RT-Thread can use the on-line software package management tool, together with system configuration tools, to achieve intuitive and rapid modular cutting, seamlessly import rich software packages; thus, achieving complex functions like Android's graphical interface and touch sliding effects, smart voice interaction effects, and so on.

RT-Thread Architecture

RT-Thread has not only a real-time kernel, but also rich components. Its architecture is as follows:

architecture

It includes:

  • Kernel layer: RT-Thread kernel, the core part of RT-Thread, includes the implementation of objects in the kernel system, such as multi-threading and its scheduling, semaphore, mailbox, message queue, memory management, timer, etc.; libcpu/BSP (Chip Migration Related Files/Board Support Package) is closely related to hardware and consists of peripheral drivers and CPU porting.

  • Components and Service Layer: Components are based on upper-level software on top of the RT-Thread kernel, such as virtual file systems, FinSH command-line interfaces, network frameworks, device frameworks, and more. Its modular design allows for high internal cohesion inside the components and low coupling between components.

  • RT-Thread software package: A general-purpose software component running on the RT-Thread IoT operating system platform for different application areas, consisting of description information, source code or library files. RT-Thread provides an open package platform with officially available or developer-supplied packages that provide developers with a choice of reusable packages that are an important part of the RT-Thread ecosystem. The package ecosystem is critical to the choice of an operating system because these packages are highly reusable and modular, making it easy for application developers to build the system they want in the shortest amount of time. RT-Thread supports 450+ software packages.

RT-Thread Features

  • Designed for resource-constrained devices, the minimum kernel requires only 1.2KB of RAM and 3 KB of Flash.
  • A variety of standard interfaces, such as POSIX, CMSIS, C++ application environment.
  • Has rich components and a prosperous and fast growing package ecosystem.
  • Elegant code style, easy to use, read and master.
  • High Scalability. RT-Thread has high-quality scalable software architecture, loose coupling, modularity, is easy to tailor and expand.
  • Supports high-performance applications.
  • Supports all mainstream compiling tools such as GCC, Keil and IAR.
  • Supports a wide range of architectures and chips.

Code Catalogue

RT-Thread source code catalog is shown as follow:

Name Description
BSP Board Support Package based on the porting of various development boards
components Components, such as finsh shell, file system, protocol stack etc.
documentation Related documents, like coding style, doxygen etc.
examples Related sample code
include Head files of RT-Thread kernel
libcpu CPU porting code such as ARM/MIPS/RISC-V etc.
src The source files for the RT-Thread kernel.
tools The script files for the RT-Thread command build tool.

RT-Thread has now been ported for nearly 200 development boards, most BSPs support MDK, IAR development environment and GCC compiler, and have provided default MDK and IAR project, which allows users to add their own application code directly based on the project. Each BSP has a similar directory structure, and most BSPs provide a README.md file, which is a markdown-format file that contains the basic introduction of BSP, and introduces how to simply start using BSP.

Resources

Supported Architectures

RT-Thread supports many architectures, and has covered the major architectures in current applications. Architecture and chip manufacturer involved:

  • ARM Cortex-M0/M0+:manufacturers like ST
  • ARM Cortex-M3:manufacturers like ST、Winner Micro、MindMotion, ect.
  • ARM Cortex-M4:manufacturers like ST、Infineon、Nuvoton、NXP、Nordic、GigaDevice、Realtek、Ambiq Micro, ect.
  • ARM Cortex-M7:manufacturers like ST、NXP
  • ARM Cortex-M23:manufacturers like GigaDevice
  • ARM Cortex-M33:manufacturers like ST
  • ARM Cortex-R4
  • ARM Cortex-A8/A9:manufacturers like NXP
  • ARM7:manufacturers like Samsung
  • ARM9:manufacturers like Allwinner、Xilinx 、GOKE
  • ARM11:manufacturers like Fullhan
  • MIPS32:manufacturers like loongson、Ingenic
  • RISC-V RV32E/RV32I[F]/RV64[D]:manufacturers like sifive、Canaan Kendrytebouffalo_labNucleiT-HeadHPMicro
  • ARC:manufacturers like SYNOPSYS
  • DSP:manufacturers like TI
  • C-Sky
  • x86

Supported IDE and Compiler

The main IDE/compilers supported by RT-Thread are:

  • RT-Thread Studio IDE
  • MDK KEIL
  • IAR
  • GCC

RT-Thread Studio IDE

User Manual | Tutorial Videos

RT-Thread Studio IDE (a.k.a. RT-Studio) is a one-stop intergrated development environment built by RT-Thread team. It has a easy-to-use graphical configuration system and a wealth of software packages and components resources. RT-Studio has the features of project creation, configuration and management,as well as code editing, SDK management, build configuration, debugging configuration, program download and debug. We're looking to make the use of RT-Studio as intuitive as possible, reducing the duplication of work and improving the development efficiency.

studio

Env Tool

User Manual | Tutorial Videos

In the early stage, RT-Thread team also created an auxiliary tool called Env. It is an auxiliary tool with a TUI (Text-based user interface). Developers can use Env tool to configure and generate the GCC, Keil MDK, and IAR projects.

env

Getting Started

RT-Thread Programming Guide | RT-Thread Studio IDE | Kernel Sample | RT-Thread Beginners Guide

Based on STM32F103 BluePill | Raspberry Pi Pico

Simulator

RT-Thread BSP can be compiled directly and downloaded to the corresponding development board for use. In addition, RT-Thread also provides qemu-vexpress-a9 BSP, which can be used without hardware platform. See the getting started guide below for details. Getting Started of QEMU with Env: Windows | Linux Ubuntu | Mac OS

License

RT-Thread follows the Apache License 2.0 free software license. It's completely open-source, can be used in commercial applications for free, does not require the disclosure of code, and has no potential commercial risk. License information and copyright information can generally be seen at the beginning of the code:

/* Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 * ...
 */

Community

RT-Thread is very grateful for the support from all community developers, and if you have any ideas, suggestions or questions in the process of using RT-Thread, RT-Thread can be reached by the following means, and we are also updating RT-Thread in real time on these channels. At the same time, any questions can be asked in the issue section of RT-Thread repository or RT-Thread forum, and community members will answer them.

Website | Github | Twitter | LinkedIn | Youtube | Facebook | Medium

Contribution

If you are interested in RT-Thread and want to join in the development of RT-Thread and become a code contributor,please refer to the Code Contribution Guide.

Thanks for the following contributors!

rt-thread's People

Contributors

aozima avatar ardafu avatar armink avatar balancetwk avatar bernardxiong avatar bigmagic123 avatar davidlin1577 avatar enkiller avatar geniusgogo avatar greedyhao avatar grissiom avatar guozhanxin avatar heyuanjie87 avatar lawlieta avatar lgnq avatar liangyongxiang avatar lymzzyh avatar murphyzhao avatar mysterywolf avatar polarvid avatar prife avatar rbb666 avatar summergift avatar supperthomas avatar weety avatar wosayttn avatar yangjie11 avatar yqiu2018 avatar z8man8 avatar zhkag avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rt-thread's Issues

关于LWIP1.4.0里面的一些小BUG


static void tcpip_init_done_callback(void *arg)  //函数中
{
#ifdef LWIP_NETIF_LINK_CALLBACK
            netif_set_link_up(ethif->netif);
#endif
}
//修正为
#if LWIP_NETIF_LINK_CALLBACK
            netif_set_link_down(ethif->netif);
#endif

按正常情况应该是先down.而后再到线程中up..还有这个预编译的宏.写法有问题.应该是


#if  (LWIP_NETIF_LINK_CALLBACK)  

#endif

//本小BUG在各个LWIP里面的API文件里面都有出现


//在线程
static void eth_rx_thread_entry(void* parameter)
{
if (status)
    netifapi_netif_set_link_up(device->netif);
else
    netifapi_netif_set_link_down(device->netif);
}
/*这两个函数应该都需要判断返回值如果返回值不为RT-EOK则需要再重新发送因为如果发送不出去的话就无法通知TCP-IP处理线程网线已经被拨除*/
//修正为
if (status)
    while(netifapi_netif_set_link_up(device->netif) != RT_EOK)
        rt-thread_deay(1);
else
    while(netifapi_netif_set_link_down(device->netif) != RT_EOK)
        rt-thread_deay(1);

dfs_elm.c在VS下编译报错。

环境:VS2012
BSP:simulator

错误信息:
在编译dfs_elm.c时报错,应该是和VC的库冲突。

1> dfs_elm.c
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\wtime.inl(44): error C2143: 语法错误 : 缺少“)”(在“”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\wtime.inl(44): error C2143: 语法错误 : 缺少“{”(在“
”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\wtime.inl(44): error C2059: 语法错误:“)”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\wtime.inl(45): error C2054: 在“Time”之后应输入“(”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\wtime.inl(47): warning C4081: 应输入“)”;找到“字符串”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\wtime.inl(52): error C2143: 语法错误 : 缺少“)”(在“
”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\wtime.inl(52): error C2143: 语法错误 : 缺少“{”(在“”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\wtime.inl(52): error C2059: 语法错误:“)”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\wtime.inl(53): error C2054: 在“Time”之后应输入“(”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(82): error C2146: 语法错误: 缺少“)”(在标识符“Time1”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(82): error C2061: 语法错误: 标识符“Time1”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(82): error C2059: 语法错误:“;”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(82): error C2059: 语法错误:“,”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(82): error C2059: 语法错误:“)”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(86): error C2143: 语法错误 : 缺少“)”(在“
”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(86): error C2143: 语法错误 : 缺少“{”(在“
”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(86): error C2059: 语法错误:“)”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(87): error C2054: 在“Time”之后应输入“(”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(89): warning C4081: 应输入“)”;找到“字符串”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(94): error C2143: 语法错误 : 缺少“)”(在“
”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(94): error C2143: 语法错误 : 缺少“{”(在“
”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(94): error C2059: 语法错误:“)”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(95): error C2054: 在“Time”之后应输入“(”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(99): error C2143: 语法错误 : 缺少“)”(在“
”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(99): error C2143: 语法错误 : 缺少“{”(在“
”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(99): error C2059: 语法错误:“)”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(100): error C2054: 在“Time”之后应输入“(”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(102): warning C4081: 应输入“)”;找到“字符串”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(107): error C2143: 语法错误 : 缺少“)”(在“
”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(107): error C2143: 语法错误 : 缺少“{”(在“”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(107): error C2059: 语法错误:“)”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(108): error C2054: 在“Time”之后应输入“(”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(112): error C2143: 语法错误 : 缺少“)”(在“
”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(112): error C2143: 语法错误 : 缺少“{”(在“
”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(112): error C2059: 语法错误:“)”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(113): error C2054: 在“Time”之后应输入“(”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(115): warning C4081: 应输入“)”;找到“字符串”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(119): error C2143: 语法错误 : 缺少“)”(在“
”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(119): error C2143: 语法错误 : 缺少“{”(在“”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(119): error C2059: 语法错误:“)”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(120): error C2054: 在“Time”之后应输入“(”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(123): error C2143: 语法错误 : 缺少“{”(在“__cdecl”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(125): warning C4244: “return”: 从“__time64_t”转换到“int”,可能丢失数据
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(127): error C2143: 语法错误 : 缺少“{”(在“__cdecl”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(129): warning C4244: “return”: 从“__time64_t”转换到“int”,可能丢失数据
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(131): error C2143: 语法错误 : 缺少“{”(在“__cdecl”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(131): error C2143: 语法错误 : 缺少“)”(在“
”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(131): error C2143: 语法错误 : 缺少“{”(在“
”的前面)
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(131): error C2059: 语法错误:“)”
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\time.inl(132): error C2054: 在“_Time”之后应输入“(”

dfs_rename should work when the new file exsits

http://linux.die.net/man/3/rename

If the link named by the new argument exists, it shall be removed and old renamed to new. In this case, a link named new shall remain visible to other processes throughout the renaming operation and refer either to the file referred to by new or old before the operation began.

But in current dfs_rename, it will return -17, i.e., EEXIST. The link above said rename could return EEXIST, but in a different situation:

EEXIST or ENOTEMPTY
The link named by new is a directory that is not an empty directory.

This bug makes rename unusable in most of the scenarios.

bug about "components\drivers\include" path

Once RT_USING_DEVICE is enabled, rt-thread\components\drivers\include should be added to the search-path of compiler.
While, if none of RT-Thread drivers bus (serial/sdio/usb/mtd/device_ipc/...) is enabled, then rt-thread\components\drivers\include will not be added.
This may be a problem..

It's better to support mount table in DFS.

It's better to support mount table, therefore, system can mount the file system automatically in initialization phase. And when storage media removed, the file system can clear mount point. When storage media ready, the file system can mount the file system automatically.

应当用变参数宏优化 rt_kprintf 的调用

当 RT_USING_CONSOLE 为假时目前时这样做的:

void rt_kprintf(const char *fmt, ...)
{
}

函数体为空了。但该函数的参数没有去除,这些参数通常为字符串,即多占了无谓的空间。可以用变参数宏进行优化,去掉此时的函数参数:

将rt_kprintf改名为 _rt_kprintf

#ifdef  RT_USING_CONSOLE 
#    define  rt_kprintf(fmt,__VA_ARGS__) \_rt_kprintf(fmt, ##__VA_ARGS__)
#else
#    define  rt_kprintf(fmt,__VA_ARGS__)
# endif

或者:

#ifdef  RT_USING_CONSOLE 
#    define  rt_kprintf(fmt, args...)  _rt_kprintf(fmt, ##args)
#else
#    define  rt_kprintf(fmt, args...)
# endif

The MSH same prefix name parse error

ex:
finsh />help
RT-Thread shell commands:
js_main - JavaScript Interpreter load file
js - JavaScript Interpreter CLI
...
finsh />js
js_main

my code:
void js(void)
{
rt_kprintf("js\n");
}
MSH_CMD_EXPORT(js, JavaScript Interpreter CLI)

int
js_main(int argc, char** argv)
{
rt_kprintf("js_main\n");
}
MSH_CMD_EXPORT(js_main, JavaScript Interpreter load file)

this example,on MSH call js,but always call js_main.

rt_interrupt_nest have different types across the source files

This is the output of git grep rt_interrupt_nest

bsp/bf533/board.c:    extern rt_uint8_t  rt_interrupt_nest;
bsp/bf533/board.c:    rt_interrupt_nest               = 0;
bsp/simulator/rtthread.def:    rt_interrupt_nest @546 DATA
libcpu/arm/AT91SAM7S/interrupt.c:extern rt_uint32_t rt_interrupt_nest;
libcpu/arm/AT91SAM7S/interrupt.c:   rt_interrupt_nest = 0;
libcpu/arm/AT91SAM7X/interrupt.c:extern rt_uint32_t rt_interrupt_nest;
libcpu/arm/AT91SAM7X/interrupt.c:   rt_interrupt_nest = 0;
libcpu/arm/AT91SAM7X/start_rvds.S:              IMPORT rt_interrupt_nest
libcpu/arm/AT91SAM7X/start_rvds.S:              LDR r0, =rt_interrupt_nest
libcpu/arm/at91sam926x/interrupt.c:extern rt_uint32_t rt_interrupt_nest;
libcpu/arm/at91sam926x/interrupt.c:    rt_interrupt_nest = 0;
libcpu/arm/cortex-r4/interrupt.c:extern volatile rt_uint8_t rt_interrupt_nest;
libcpu/arm/cortex-r4/interrupt.c:   rt_interrupt_nest = 0;
libcpu/arm/lpc214x/cpuport.c:extern rt_uint32_t rt_interrupt_nest;
libcpu/arm/lpc214x/cpuport.c:   rt_interrupt_nest = 0;
libcpu/arm/lpc24xx/interrupt.c:extern rt_uint32_t rt_interrupt_nest;
libcpu/arm/lpc24xx/interrupt.c: rt_interrupt_nest = 0;
libcpu/arm/s3c24x0/interrupt.c:extern rt_uint32_t rt_interrupt_nest;
libcpu/arm/s3c24x0/interrupt.c:    rt_interrupt_nest = 0;
libcpu/arm/s3c44b0/interrupt.c:extern rt_uint32_t rt_interrupt_nest;
libcpu/arm/s3c44b0/interrupt.c: rt_interrupt_nest = 0;
libcpu/arm/sep4020/interrupt.c:extern rt_uint32_t rt_interrupt_nest;
libcpu/arm/sep4020/interrupt.c:    rt_interrupt_nest = 0;
libcpu/avr32/uc3/exception_gcc.S:  lda.w   r12, rt_interrupt_nest       /* Is nested interrupt? */
libcpu/avr32/uc3/exception_gcc.S:  lda.w   r12, rt_interrupt_nest       /* Is nested interrupt? */
libcpu/avr32/uc3/exception_gcc.S:  lda.w   r12, rt_interrupt_nest       /* Is nested interrupt? */
libcpu/avr32/uc3/exception_gcc.S:  lda.w   r12, rt_interrupt_nest       /* Is nested interrupt? */
libcpu/ia32/interrupt.c:extern rt_uint32_t rt_interrupt_nest;
libcpu/ia32/interrupt.c:    rt_interrupt_nest = 0;
libcpu/m16c/m16c62p/cpuport.c:extern volatile rt_uint8_t rt_interrupt_nest;
libcpu/m16c/m16c62p/cpuport.c:    rt_interrupt_nest               = 0;
libcpu/mips/jz47xx/interrupt.c:extern rt_uint32_t rt_interrupt_nest;
libcpu/mips/jz47xx/interrupt.c: rt_interrupt_nest = 0;
libcpu/mips/loongson/interrupt.c:extern rt_uint32_t rt_interrupt_nest;
libcpu/mips/loongson/interrupt.c:   rt_interrupt_nest = 0;
libcpu/mips/loongson_1b/interrupt.c:extern rt_uint32_t rt_interrupt_nest;
libcpu/mips/loongson_1b/interrupt.c:    rt_interrupt_nest = 0;
libcpu/ppc/ppc405/interrupt.c:extern volatile rt_uint8_t rt_interrupt_nest;
libcpu/ppc/ppc405/interrupt.c:  rt_interrupt_nest = 0;
libcpu/v850/70f34/cpuport.c:extern volatile rt_uint8_t rt_interrupt_nest;
libcpu/v850/70f34/cpuport.c:    rt_interrupt_nest               = 0;
libcpu/xilinx/microblaze/trap.c:extern rt_uint32_t rt_interrupt_nest;
libcpu/xilinx/microblaze/trap.c:    rt_interrupt_nest = 0;
src/irq.c:volatile rt_uint8_t rt_interrupt_nest;
src/irq.c:                                rt_interrupt_nest));
src/irq.c:    rt_interrupt_nest ++;
src/irq.c:                                rt_interrupt_nest));
src/irq.c:    rt_interrupt_nest --;
src/irq.c:    return rt_interrupt_nest;
src/object.c:    extern volatile rt_uint8_t rt_interrupt_nest;
src/object.c:    if (rt_interrupt_nest != 0)
src/scheduler.c:extern volatile rt_uint8_t rt_interrupt_nest;
src/scheduler.c:                          rt_interrupt_nest,
src/scheduler.c:            if (rt_interrupt_nest == 0)

Some where declare it as uint32_t or uint8_t while actually it should be volatile uint8_t.

This lead to link error in CCS with high optimization level.

Maybe we should declare it in rtdef.h.

Failed to build stm32f0x

AS build/Libraries/CMSIS/ST/STM32F0xx/Source/Templates/gcc_ride7/startup_stm32f0xx.o Libraries/CMSIS/ST/STM32F0xx/Source/Templates/gcc_ride7/startup_stm32f0xx.s:
Assembler messages: Libraries/CMSIS/ST/STM32F0xx/Source/Templates/gcc_ride7/startup_stm32f0xx.s:92: Error: cannot honor width suffix -- `str r3,[r2],#4'
scons: *** [build/Libraries/CMSIS/ST/STM32F0xx/Source/Templates/gcc_ride7/startup_stm32f0xx.o] Error 1

https://travis-ci.org/rogerz/rt-thread/jobs/4533546

文件名包含空格,显示的问题。

axi82 >>
elmfat文件系统当文件名中含有空格时有点问题。
用ls命令列出目录文件时带空格的文件名显示不正常。
如文件名为he llo.c文件名,ls命令列出目录时只显示he。后面的全部不显示了。

需要尝试,检查是否存在这样的问题。

pthread_cond_init may lead to NULL reference

man pthread_cond_init:

The  pthread_cond_init()  function  shall initialize the condition variable referenced by cond with 
attributes referenced by attr. If attr is NULL, the default condition variable attributes shall be used...

But if we do pthread_cond_init(&cond, RT_NULL), it will get a NULL reference on line 101 of components/pthreads/pthread_cond.c.

This issue is found by Clang.

关于IIC总线接口的重写

最新版本库里的总线接口不是严格按照spi总线架构来编写的,所以我想按照SPI总线架构来重新实现,已经应用了新的接口,和spi总线架构一样,方便理解和移植,有必要吗?

关于软件定时器的一些异常问题

各位,

最近用软件定时器出现了一些问题,就是用着用着,内核定时器处理任务timer的ticks也不增加,定时器ticks也不增加,之后开启定时器也开启不了,但是开启别的定时器,就可以恢复内核定时器处理任务timer的继续执行。

关于软件定时器是不是有些陷阱,我不知道?

关于 rtgui_theme.c中画radiobox 的函数rtgui_theme_draw_radiobox(struct rtgui_radiobox *radiobox)

这个函数在在画的时候判断边界有问题,导致某些项目画不上或画不完整,下面给出我的修改,请确认。
包含两个改动:
1 判断边界(618行 、657行) 分别修改为
if (item_rect.y2 > (rect.y2 - bord_size/2 - 1)) break;
if (item_rect.x2 > (rect.x2 - bord_size/2 - 1)) break;
2 不适当的项目宽度减一 (677行) 估计是为了配合原来不适当的代码而减一 修改为:
item_rect.x2 += item_size;

修改后的函数:
void rtgui_theme_draw_radiobox(struct rtgui_radiobox *radiobox)
{
struct rtgui_dc *dc;
struct rtgui_rect rect, item_rect;
int item_size, bord_size, index;
rtgui_color_t fc;

/* begin drawing */
dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(radiobox));
if (dc == RT_NULL) return;

/* get widget rect */
rtgui_widget_get_rect(RTGUI_WIDGET(radiobox), &rect);
rtgui_dc_fill_rect(dc, &rect);

item_size = radiobox->item_size;
/* get board size */
if (radiobox->orient == RTGUI_VERTICAL)
    bord_size = item_size;
else
{
    rtgui_font_get_metrics(RTGUI_DC_FONT(dc), "H", &item_rect);
    bord_size = rtgui_rect_height(item_rect);
}

/* draw box */
rtgui_rect_inflate(&rect, -bord_size / 2);
fc = RTGUI_WIDGET_FOREGROUND(radiobox);

RTGUI_WIDGET_FOREGROUND(radiobox) = white;
rect.x1 ++;
rect.y1 ++;
rect.x2 ++;
rect.y2 ++;
rtgui_dc_draw_rect(dc, &rect);

RTGUI_WIDGET_FOREGROUND(radiobox) = RTGUI_RGB(128, 128, 128);
rect.x1 --;
rect.y1 --;
rect.x2 --;
rect.y2 --;
rtgui_dc_draw_rect(dc, &rect);

RTGUI_WIDGET_FOREGROUND(radiobox) = fc;

rtgui_rect_inflate(&rect, bord_size / 2);
if (radiobox->text != RT_NULL)
{
    struct rtgui_rect text_rect;

    /* draw group text */
    rtgui_font_get_metrics(RTGUI_DC_FONT(dc), radiobox->text, &text_rect);
    rtgui_rect_moveto(&text_rect, rect.x1 + bord_size + 5, rect.y1);
    rect.x1 -= 5;
    rect.x2 += 5;
    rtgui_dc_fill_rect(dc, &text_rect);
    rect.x1 += 5;
    rect.x2 -= 5;
    rtgui_dc_draw_text(dc, radiobox->text, &text_rect);
}

/* set init item rect */
item_rect = rect;
rtgui_rect_inflate(&item_rect, - bord_size);
if (radiobox->orient == RTGUI_VERTICAL)
{
    rt_uint16_t offset;

    /* set the first text rect */
    item_rect.y2 = item_rect.y1 + item_size;

    offset = (item_size - RADIO_BOX_H) / 2;
    /* draw each radio button */
    for (index = 0; index < radiobox->item_count; index ++)
    {
        if (item_rect.y2 > rect.y2 -  bord_size/2 - 1) break;

        /* draw radio */
        if (radiobox->item_selection == index)
        {
            if (RTGUI_WIDGET_IS_FOCUSED(radiobox))
                rtgui_dc_draw_focus_rect(dc, &item_rect);

            rtgui_dc_draw_word(dc, item_rect.x1, item_rect.y1 + offset, RADIO_BOX_H, radio_checked_byte);
        }
        else
        {
            rtgui_dc_draw_word(dc, item_rect.x1, item_rect.y1 + offset, RADIO_BOX_H, radio_unchecked_byte);
        }

        /* draw text */
        item_rect.x1 += item_size + 3;
        rtgui_dc_draw_text(dc, radiobox->items[index], &item_rect);
        item_rect.x1 -= item_size + 3;

        item_rect.y1 += item_size;
        item_rect.y2 += item_size;
    }
}
else
{
    /* set the first text rect */
    item_rect.x2 = item_rect.x1 + item_size;
    item_rect.y2 = item_rect.y1 + bord_size;

    /* draw each radio button */
    for (index = 0; index < radiobox->item_count; index ++)
    {
        if (item_rect.x2 > rect.x2 - bord_size/2 - 1) break;

        /* draw radio */
        if (radiobox->item_selection == index)
        {
            if (RTGUI_WIDGET_IS_FOCUSED(radiobox))
                rtgui_dc_draw_focus_rect(dc, &item_rect);
            rtgui_dc_draw_word(dc, item_rect.x1, item_rect.y1, RADIO_BOX_H, radio_checked_byte);
        }
        else
        {
            rtgui_dc_draw_word(dc, item_rect.x1, item_rect.y1, RADIO_BOX_H, radio_unchecked_byte);
        }

        /* draw text */
        item_rect.x1 += bord_size + 3;
        rtgui_dc_draw_text(dc, radiobox->items[index], &item_rect);
        item_rect.x1 -= bord_size + 3;

        item_rect.x1 += item_size;
        item_rect.x2 += item_size;
    }
}

/* end drawing */
rtgui_dc_end_drawing(dc);

}

SConstruct的一些问题

bsp\stm32f10x>scons --target=cb -s
TypeError: 'NoneType' object is not iterable:
  File "E:\work\rt-thread\rt-thread_git_fork\bsp\stm32f10x\SConstruct", line 40:
    EndBuilding(TARGET)
  File "E:\work\rt-thread\rt-thread_git_fork\tools\building.py", line 342:
    CBProject('project.cbp', Projects, program)
  File "E:\work\rt-thread\rt-thread_git_fork\tools\codeblocks.py", line 62:
    CB_AddHeadFiles(program, elem, project_path)
  File "E:\work\rt-thread\rt-thread_git_fork\tools\codeblocks.py", line 15:
    for item in program:    

经查问题出在 SConstruct 的末尾:

# build program 
env.Program(TARGET, objs)

# end building 
EndBuilding(TARGET)

这块是应该修改成:

# make a building
DoBuilding(TARGET, objs)

还是

# build program 
+program = env.Program(TARGET, objs)

# end building 
+EndBuilding(TARGET, program)

RT-THREAD1.1.0 kernel下semaphore_buffer_worker.c文件的注释问题

该文件位于:https://github.com/RT-Thread/rt-thread/blob/master/examples/kernel/semaphore_buffer_worker.c

原文:
/*

  • 程序清单:信号量实现生产者消费者间的互斥
    *
  • 在这个程序中,会创建两个线程,一个是生成者线程worker一个是消费者线程thread
    *
  • 在数据信息生产、消费的过程中,worker负责把数据将写入到环形buffer中,而thread
  • 则从环形buffer中读出。
    /
    建议修改:
    /
  • 程序清单:信号量实现生产者消费者间的互斥
    *
  • 在这个程序中,会创建两个线程,一个是生成者线程worker一个是消费者线程consumer
    *
  • 在数据信息生产、消费的过程中,worker负责把数据将写入到环形buffer中,而consumer
  • 则从环形buffer中读出。
    */

原文134行
/* 生产者线程入口 /
static void thread_entry(void
parameter)
这里明显是消费者线程,注释有误
建议修改为:
/* 消费者线程入口 /
static void consumer_entry(void
parameter)

原文205行
/* 创建线程1 /
tid = rt_thread_create("thread",
thread_entry, RT_NULL, /
线程入口是thread_entry, 入口参数是RT_NULL /
THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
建议修改为:
/
创建消费者线程 /
tid = rt_thread_create("consumer",
consumer_entry, RT_NULL, /
消费者线程入口是consumer_entry, 入口参数是RT_NULL */
THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE);

原文215行:
/* 创建线程2 /
建议修改为:
/
创建生产者线程 */

不改也不影响编译,但不利于初学者直观理解。

PIC32部分代码编译失败

PIC32 enternet starter kit,rt-thread代码用C32编译失败。
In file included from c:\program files (x86)\microchip\mplab c32 suite\bin../lib/gcc/pic32mx/4.5.1/../../../../pic32mx/include/stdlib.h:7:0,
from ....\components\finsh\finsh_token.c:31:
c:\program files (x86)\microchip\mplab c32 suite\bin../lib/gcc/pic32mx/4.5.1/../../../../pic32mx/include/stddef.h:78:19: error: conflicting types for 'size_t'
../../components/finsh/finsh.h:75:22: note: previous declaration of 'size_t' was here
....\components\finsh\finsh_token.c: In function 'finsh_token_init':
....\components\finsh\finsh_token.c:75:2: warning: incompatible implicit declaration of built-in function 'memset'
....\components\finsh\finsh_token.c: In function 'finsh_token_get_token':
....\components\finsh\finsh_token.c:90:2: warning: incompatible implicit declaration of built-in function 'strncpy'
....\components\finsh\finsh_token.c: In function 'token_next_char':
....\components\finsh\finsh_token.c:130:29: warning: incompatible implicit declaration of built-in function 'strlen'
....\components\finsh\finsh_token.c: In function 'token_proc_number':
....\components\finsh\finsh_token.c:529:50: warning: incompatible implicit declaration of built-in function 'strlen'

RT-Thread + Keil

Hi All,

Can you explain me how to create a project version for KEIL suite.
I use some EFM32GG and EFM32WG.

Nothing work in python script.

B.Regards
Christophe.

Finsh初始化顺序的Bug

当RTT开启finsh后,如果在系统刚刚启动,还没到finsh_set_device()过程中在控制台中输入按键,这时系统会断言停在RT_ASSERT(rx_fifo != RT_NULL)位置。

bernard已回复:这个时候finsh还没去打开串口设备,所以有问题

elm fatfs: ERROR "FR_NO_FILE" will be raised when creating a file in an directory with many entires.

Error "FR_NO_NAME" will be raised up, when creating a more file in an directory with too many entries. Hower it should be "FR_DENIED" or something better.

FR_DENIED
The required access was denied due to one of the following reasons:
Write mode open against the read-only file.
Deleting the read-only file or directory.
Deleting the non-empty directory or current directory.
Reading the file opened without FA_READ flag.
Any modification to the file opened without FA_WRITE flag.
Could not create the file or directory due to the directory table is full.
Could not create the directory due to the volume is full.

more: http://elm-chan.org/fsw/ff/en/rc.html

more: http://blog.csdn.net/leonwei/article/details/3980179

Test code (tested in simulator)

#include <dfs_posix.h>
static void rt_test_thread_entry(void *parameter)
{
    static int count;
    static char buf[64];
    int fd;
    for(;;)
    {
        rt_sprintf(buf, "/disk/sd/%08d.dat", count++);
        fd = open(buf, O_RDWR|O_APPEND|O_CREAT, 0);
        if (fd < 0)
        {
            rt_thread_t tid;
            tid = rt_thread_self();

            rt_kprintf("error <%d>! could not create file <%s>\n", tid->error, buf);
            /* FIXME */
            return ;
        }
        close(fd);
    }
}


    tid = rt_thread_create("test",
                           rt_test_thread_entry, RT_NULL,
                           2048, RT_THREAD_PRIORITY_MAX * 3 / 4, 20);
    if (tid != RT_NULL)
        rt_thread_startup(tid);

complie failure when config as using Modbus Slave only

in user_mb_app.c , there is :

if (xMBMasterGetCBRunInMasterMode())

so undefined symbol error if using modbus slave only.
suggest using macro define:

#if defined(RT_MODBUS_MASTER_SLAVE_RTU)
    if (xMBMasterGetCBRunInMasterMode())
#elif defined(RT_MODBUS_SLAVE_RTU)
    if (0)
#elif defined(RT_MODBUS_MASTER_RTU)
    if (1)
#endif

初始化顺序错误

/* init application */
rt_application_init();
............................................

/* init timer thread */
rt_system_timer_thread_init();

这两个函数的初始化应该是有顺序规定的,因为在application_init里面可能会创建soft timer,而此时都还没有对soft timer进行初始化,所以需要将目前这个顺序进行颠倒过来:
/* init timer thread /
rt_system_timer_thread_init();
/
init application */
rt_application_init();

关于事件IPC接口的问题

各位,
现有事件模型中在处理多个事件同时触发的时候,只能使用rt_event_send()函数设置该事件,但是有的时候事件条件不满足的时候需要撤销该事件,这样做有无意义呢?是否能够考虑加入这个功能呢?

case sensitive folder name in DFS/elmfat parition

Step to reproduce:

  1. On RealBoard4088, create a "SD" folder and mount TF card to it.
msh /SD>ls /
Directory /:
bin                 <DIR>                    
resource            <DIR>                    
upgrade.rb4         478096                   
SD                  <DIR>                    
prog                <DIR>                    
  1. reboot and cd sd in msh(note the lower case name).
  2. ls will show an empty folder:
msh /sd>ls
Directory /sd:

However, the files in SD/ is OK.

SDIO初始化对SD card高速模式判断设置的问题

BSP: AT91SAM9260
在SDIO驱动初始化中,对host->flags赋值如下:
host->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE;
并未设置MMCSD_SUP_HIGHSPEED标志.所以下面这段代码应该在判断此标志时会返回,但是从板子实际运行的情况来看,此标志被设置了,但搜索代码并未发现设置该flag.
可能出现问题处的代码:


static rt_int32_t sdio_set_highspeed(struct rt_mmcsd_card *card)
{
    rt_int32_t ret;
    rt_uint8_t speed;

    if (!(card->host->flags & MMCSD_SUP_HIGHSPEED)) 
        return 0;

    if (!card->cccr.high_speed)
        return 0;

    speed = sdio_io_readb(card->sdio_function[0], SDIO_REG_CCCR_SPEED, &ret);
    if (ret)
        return ret;

    speed |= SDIO_SPEED_EHS;

    ret = sdio_io_writeb(card->sdio_function[0], SDIO_REG_CCCR_SPEED, speed);
    if (ret)
        return ret;

    card->flags |= CARD_FLAG_HIGHSPEED;

    return 0;
}

建议发布新版本时打上标签

RTGUI都打了标签了,不知为何这里不打。
发现最新代码上的simulator有问题,现在没有标签都不知checkout哪个好。
现在也可以对旧的commit打标签。

rt_kprintf的时候,被抢占

如下(mq实验时的设备输出):
W25Q16BV or W25Q16CL or W25Q16CV detection
File System initialized!
thread2: send message - this is message No.0
thread2: send message - this is message No.1
thread2: send message - this is message No.2
thread2: send message - this is message No.3
thread2: send message thread3: send an urgent message
thread1: recv a msg, the content: this is an urgent message!
thread1: recv a msg, the content: this is message No.0
thread1: recv a msg, the content: this is message No.1
thread1: recv a msg, the contenthe content: this is messthread2: send message - this is message No.5
thread2: send message - this is message No.6
thread2: send message - this is message No.7
thread2: send message - this is message No.8
thmessage No.9
ge No.2
thread1: recv a msg, the content: this is message No.3
thread1: recv a msg, the content: this is message No.4
thread1: recv a msg, the content: this is message No.5
发现在用串口往外发送数据时,线程被换出,不知道有没问题?
版本:1.1.0

compile warning on components/dfs/src/dfs_posix.c

Compile with gcc -Wall gives:

/win_back/projects/rt-thread/rt-thread/components/dfs/src/dfs_posix.c: In function 'readdir':
/win_back/projects/rt-thread/rt-thread/components/dfs/src/dfs_posix.c:545:29: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]

a bug when i build 4_gui_examples


diff --git "a/C:\\Users\\yangyang\\AppData\\Local\\Temp\\TortoiseGit\\dem6C68.tmp\\demo_view_listctrl-38f1c4e-left.c" "b/C:\\Work\\MCU_Software\\rt-thread\\examples\\gui\\demo_view_listctrl.c"
index 166e441..736fb0a 100644
--- "a/C:\\Users\\yangyang\\AppData\\Local\\Temp\\TortoiseGit\\dem6C68.tmp\\demo_view_listctrl-38f1c4e-left.c"
+++ "b/C:\\Work\\MCU_Software\\rt-thread\\examples\\gui\\demo_view_listctrl.c"
@@ -254,7 +254,7 @@ rtgui_container_t *demo_view_listctrl(void)
 
     rect.y1 = rect.y2 + 3;
     rect.y2 = 250;
-    box = rtgui_listctrl_create((rt_uint32_t)items, sizeof(items) / sizeof(items[0]), &rect,
+    box = rtgui_listctrl_create((void *)items, sizeof(items) / sizeof(items[0]), &rect,
                                 _rtgui_listctrl_item_draw);
     rtgui_listctrl_set_onitem(box, on_items);
     /* container是一个container控件,调用add_child方法添加这个listctrl控件 */

The readid in MTD_NAND is not usable

struct rt_mtd_nand_driver_ops
{
    rt_err_t (*read_id) (struct rt_mtd_nand_device* device);
...
}
rt_inline rt_uint32_t rt_mtd_nand_read_id(struct rt_mtd_nand_device* device)
{
    return device->ops->read_id(device);
}

should be fixed.

关于新串口框架

各位,

修改了串口框架以后,貌似没有给出测试的例子,特别的dma的例子,还有关于dma接收时候的timeout机制,能不能指定一个bsp来实现一下,大家才能更好的理解你们从写框架的初衷!谢谢。。。

simulator不能使用外部字体文件。

环境:VS2012
BSP:simulator

描述:已经确定在finsh shell中可以访问字体文件,调试后发现GUI的字体系统比文件系统要更早初始化。

RTGUI: could not open the font file:/resource/hzk16.fnt
RTGUI: please mount the fs first and make sure the file is there
RTGUI: could not open the font file:/resource/hzk12.fnt
RTGUI: please mount the fs first and make sure the file is there
win32 share directory initialized!

sqlite移植stm32讨论

看到一个sqlite的移植,但是搞不懂到底是怎么移植过去的,我的理解是直接把sqlite3.c文件放在目录里,编译掉,然后再调用finish的命令行,但是实际上编译sqlite3.c的时候遇到很多问题,所以猜想做着不是这么做的,但是又不清楚怎么弄,作者实在搞得太简洁了,初学者根本看不懂的说。。。。。求助个!

Sconscript添加.lib库文件生成keil工程

有库文件‘a.lib’,在Sconscript文件中采用如下形式添加库文件到工程:
==代码==============
LIBS = ['a']
DefineGroup('A', src, CPPPATH = CPPPATH, LIBS = LIBS, LIBPATH=LIBPATH)
==代码==============
这样生成的keil工程目录下会有两个同名的‘A’目录,一个里面放的是'.c'等源代码文件,另一个里面则单独放置一个'.lib'文件,同时尝试了添加两个‘.lib’文件,果然keil下又多了个同名目录单独放置新添加的库文件,不知能否改善下。

dfs_unmount bug

dfs_unmount("/a-none-exsit-path") will unmount an valid filesystem.
in simulator: dfs_umount("/dev/abc") will unmount the root fs.
This is dangerous and should be fixed.

Mark here, I will fix it tomorrow.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.