feilipu / arduino_freertos_library Goto Github PK
View Code? Open in Web Editor NEWA FreeRTOS Library for all Arduino ATmega Devices (Uno R3, Leonardo, Mega, etc).
License: MIT License
A FreeRTOS Library for all Arduino ATmega Devices (Uno R3, Leonardo, Mega, etc).
License: MIT License
Hello Phillip,
I find the 15 ms time slice is still too large to meet the requirement of something like robotic control. I noticed another task management library for TaskManagerIO on https://github.com/davetcc/TaskManagerIO, which supports microsecond-level scheduling and works with Arduino IDE. Is there a way to introduce timer 0,1 properly into freertos into Arduino IDE?
Best regards
In both Blink_AnalogRead.ino and AnalogRead_DigitalRead.ino, when creating the tasks the comment says:
// Priority, with 1 being the highest, and 4 being the lowest.
This, based to empirical testing, is wrong. Additionally, the FreeRTOS documentation (http://www.freertos.org/RTOS-task-priority.html) says
Low priority numbers denote low priority tasks.
Regards.
`#include <STM32FreeRTOS.h>
#include <Servo.h>
Servo myservo;
int pos = 0;
void vTask1(void *pvParameters){
myservo.attach(PA7);
for(;;)
{
for(pos = 0; pos < 90; pos += 1){
myservo.write(pos);
vTaskDelay(20 / portTICK_PERIOD_MS);
}
vTaskDelay(255 / portTICK_PERIOD_MS);
for(pos = 90; pos>=1; pos-=1) {
myservo.write(pos);
vTaskDelay(20 / portTICK_PERIOD_MS);
}
vTaskDelay(255 / portTICK_PERIOD_MS);
}
}
void setup() {
xTaskCreate(vTask1,NULL,64,NULL,1,NULL);
}
void loop(){
;
}`
This is my code , this code can not work in the STM32FreeRTOS.But this code can work in the arduino.I can't find the reason.
I ran the Blink_AnalogRead example on a Arduino Uno and it ran OK. Then I added some code to the loop() function to check the stack space for the idle task. Then I changed configMINIMAL_STACK_SIZE from 192 to 212, and the stack high water mark didn't change.
How can I change the stack space available to the idle process?
Some related questions: is the line
#define configMINIMAL_STACK_SIZE ( ( portSTACK_TYPE ) 192 )
correct, in particular, is it correct to cast the number to portSTACK_TYPE, which is #defined to uint8_t in portmacros.h? Should the definition of portSTACK_TYPE be changed to uint16_t? (I've asked similar questions about the types on the FreeRTOS forum.)
Here's my stack testing code:
`
volatile int loopcount = 0;
// This function calls itself recursively to a depth of n, and does a simple check
// to try to detect stack corruption.
int memtest(int n)
{
Serial.print(n); Serial.print(' '); //%10);
if (n%50 == 0) Serial.println("");
int n1;
if (n) {
n1 = memtest(n-1);
if (n1 != (n-1)) {
Serial.println("");
Serial.print("n=");
Serial.print(n);
Serial.print(" n1=");
Serial.println(n1);
while(1) {};
}
}
Serial.print(n); Serial.print(' ');
if (n%50 == 49) Serial.println("");
return n;
}
void MemTest(void pvParameters)
{
while(1) {
configSTACK_DEPTH_TYPE uxHighWaterMark;
/ Inspect our own high water mark on entering the task. */
uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL ); // not UBaseType_t which is unsigned char!
Serial.print(F("HighWaterMark "));
//vTaskDelay( 30 / portTICK_PERIOD_MS ); // wait 2 ticks
Serial.println(uxHighWaterMark);
//vTaskDelay( 30 / portTICK_PERIOD_MS ); // wait 2 ticks
if (++loopcount == 50) while (1);
Serial.println(F("hi1"));
memtest(6); // <----- Increase this number to use more of the stack.
Serial.println(F("hi2"));
}
}
void loop(void)
{
MemTest(NULL);
}
`
When I create a task to read from the SD card using:
File myFile = SD.open("temp.txt",FILE_READ);
The file can't be opened. I tried placing noInterrupts(); in various places with no luck, as well as increasing the stack size for the task.
I can both read and write from the same file in the setup, the issue only occurs when placing the code in a task.
Hi feilipu:
I see the origin FreeRTOS code in https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/include/task.h.
The define of TaskHandle_t is below:
struct tskTaskControlBlock; /* The old naming convention is used to prevent breaking kernel aware debuggers. */
typedef struct tskTaskControlBlock * TaskHandle_t;
But in your task.h,it is TaskControlBlock_t *.
And I can't search the define of TaskControlBlock_t.
I downloaded the library from eclipse. Upon first time compile, I get the following error:
C:\Users\timot\AppData\Local\Temp\ccD1BiXm.ltrans0.ltrans.o: In function
vPortYieldFromTick':
C:/Users/timot/.arduinocdt/libraries/FreeRTOS/10.0.0-3/src/port.c:478: undefined reference to __EIND__' C:/Users/timot/.arduinocdt/libraries/FreeRTOS/10.0.0-3/src/port.c:487: undefined reference to
EIND'
C:\Users\timot\AppData\Local\Temp\ccD1BiXm.ltrans0.ltrans.o: In function vPortYield': C:/Users/timot/.arduinocdt/libraries/FreeRTOS/10.0.0-3/src/port.c:461: undefined reference to
EIND'
C:/Users/timot/.arduinocdt/libraries/FreeRTOS/10.0.0-3/src/port.c:463: undefined reference to __EIND__' C:\Users\timot\AppData\Local\Temp\ccD1BiXm.ltrans0.ltrans.o: In function
xPortStartScheduler':
C:/Users/timot/.arduinocdt/libraries/FreeRTOS/10.0.0-3/src/port.c:434: undefined reference to __EIND__'
Describe the issue
C:\Users\LAF\Documents\Arduino\RTOS_example\RTOS_example.ino: In function 'void setup()':
C:\Users\LAF\Documents\Arduino\RTOS_example\RTOS_example.ino:14:15: warning: ISO C++ forbids declaration of 'type name' with no type [-fpermissive]
, (const portCHAR *)"Blink" // A name just for humans
^~~~~~~~
RTOS_example:14:9: error: expected primary-expression before 'const'
, (const portCHAR *)"Blink" // A name just for humans
^~~~~
Compiles if that portion of statement is removed. i.e. ", Blink" only.
Desktop (please complete the following information):
Win 10
Arduino 1.8.16
I have a few doubts regarding this project, which I'd like to get cleared:
xTaskCreate()
function support functions that are not of the void
type ?Thanks in advance ! :)
Hi Phillip,
configSUPPORT_STATIC_ALLOCATION
is broken again. Basically you just need to reapply this commit.
Best,
Flössie
Hello there. Awesome work by bringing the powerful FreeRTOS to Arduino boards.
One question. Is there any way this can be used on ESP32?
Is there any possibility to use AWS FreeRTOS ESP32 demos such as ble, ota and wifi_provisioning with this core of yours?
Looking forward to hearing from you soon.
Thanks in advance.
Here, I have a minimal example of FreeRTOS on an Arduino Mega 2560 with one task and the idle hook activated.
//FreeRTOS definitions
TaskHandle_t worker_task_handle = NULL;
//prototypes
void worker_task(void* pvParameters);
void setup() {
//configure serial port
Serial.begin(9600);
Serial.println("\r\n\r\nStart...\r\n");
//create task
BaseType_t result = xTaskCreate(
worker_task, //address of task function
"worker_task", //name of task
128L, //task stack size in words: 128*2=256 bytes
NULL, //task parameters
2, //task priority
&worker_task_handle //pointer to task handle
);
configASSERT(result == pdPASS); //assert that the task could be created
configASSERT(worker_task_handle != NULL); //assert that task handle is valid
}
//idle task function
void loop()
{
//Serial.println("idle...");
}
void worker_task(void* pvParameters) {
Serial.println("worker_task started...");
vTaskDelay(pdMS_TO_TICKS(1000));
}
When the worker_task
runs, it prints "worker_task started...", and then it finishes after 1000ms (after the delay). Unexpectedly, after the worker_task
has finished, the Arduino Mega 2560 restarts. I also use FreeRTOS on an ST NUCLEO L433RC-P (Cortex M4) in combination with the ST HAL driver, and there, the same example does not force a restart.
If I don't start the task in the setup()
function, then the idle task still works and no restart is performed.
My expected behaviour is, that after the worker_task
has finished, the idle task should run forever. I don't want that the Arduino Mega 2560 restarts automatically.
Is there any possibility to change this behaviour or to investigate what causes the restart?
Best,
flo2k
Describe the issue
Users expect to use delay()
which breaks FreeRTOS. So define it to be useful.
Expected behavior
Using delay()
breaks everything. Redefine it to vTaskDelay()
to stop that happening.
Additional context
See discussion here.
Hi,
It is possible to make this more generic to make porting to other platforms easier? For example an esp32 support would be difficult?
Thanks,
Nick
Hello.
If you try to use malloc()
inside task, it will always return 0.
This simple code
#include <Arduino_FreeRTOS.h>
void *bugTask(void* params){
void *ptr = pvPortMalloc(1);
while(true);
}
void setup() {
xTaskCreate(bugTask, "bug", 150, NULL, 1, NULL);
}
void loop() {}
causes LED to flash rapidly => heap overflow
Tested on Arduino UNO and Mega
I've found this article, but i don't know how to fix it in described way
#define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000 ) )
If TickType_t defined as uint16_t xTimeInMs * configTICK_RATE_HZ overflows with xTimeInMs = 1058.
Hi Phillip,
I recently got hold of some AVR128DB28. Though they are pretty new, Spence Konde already supports them with DxCore. They belong to the megaavr
family of controllers that feature a PIT instead of a WDT.
I'm trying to port the Arduino_FreeRTOS_Library to the PIT and have started a branch here. It's completely WIP, but already compiles and runs for a few ticks.
The first nicety I came across was that megaavr
s have a "Timer/Counter type B" which is defined as TCB_t
in the toolchain headers. 😒 I've thus renamed FreeRTOS' TCB_t
, but there must be a better workaround.
Now the problem is the premature halt after some ticks. Seems like the serial freaks out although there's no output from the blink task, then the PIT interrupt stops. Can you give me some hints concerning debugging or architectural differences between avr
and megaavr
?
Best,
Flössie
There should be a way to set such a file on a per project basis, instead of per platform. It's not easy even when compiling Arduino on the command line, but the newbies (I mean, the majority of users) might not find their way.
Hi, I really appreciate your work. Do you need more examples? If you need, I can submit some PR about the use of FreeRtOS API.
Hello Phillip,
The *GiveFromISR()
functions have a pxHigherPriorityTaskWoken
parameter. This can be optionally NULL, but the examples make use of it, stating the actual macro used here is port specific.
What's the right macro to use in this AVR port from your point of view? And if it's a macro (and not a function), can it be handled port agnostic using some #ifdef
s?
Thanks,
Flössie
Hi, first of all thank you for porting FreeRTOS to Arduino R4 too!
I am using Arduino IDE 2.x and I seems unable to change the option
#define INCLUDE_uxTaskGetStackHighWaterMark (1)
If I create a
FreeRTOSConfig.h
inside my sketch, include it before Arduino_FreeRTOS.h but it seems ignored.
The only way to get it wortking is to edit the FreeRTOSConfig.h inside the library, which seems quite ugly.
Do you have some suggestions to be able to get it on per-sketch basis?
Thank you!
Referencing the issue raised with Arduino-CI actions.
Arduino CI doesn't provide avr-libc headers, so the tests fail.
Issue #11
I know this is maybe a longshot but, im trying to port my code to the R4 because of memory issues on my regular uno R3.
FreeRTOS worked super well on the R3, but i just need more features, more tasks, and i just simply didn't have enough RAM on the old platform.
Im trying to build Arduino freertos but obviously, there's no avr.h on the renesas chip, and my compiler fails right there.
Compiling .pio/build/uno/lib195/FreeRTOS/port.c.o
In file included from .pio/libdeps/uno/FreeRTOS/src/Arduino_FreeRTOS.h:64,
from .pio/libdeps/uno/FreeRTOS/src/event_groups.c:38:
.pio/libdeps/uno/FreeRTOS/src/FreeRTOSConfig.h:32:10: fatal error: avr/io.h: No such file or directory
32 | #include <avr/io.h>
| ^~~~~~~~~~
compilation terminated.
Is there any way I can help maybe, include support for the other arduino chips? I'd like to be able to keep using freertos in my project. Any advice or how i could get started would be super helpful thanks.
I was developing a home project, and need to make a 5 minutes delay. Of course, I use delay(300000);
, but when I compile and upload the code, the delay was approximately of 1 minute.
Since I have experience with c++ and arduino, I dig in the repository code and found that the delay()
function was defined as vPortDelay()
, so i search it's definition.
When I found it, discover that in line 651 "vTaskDelay( (TickType_t) (ms) / portTICK_PERIOD_MS );
" is casting an unsigned long
to a TickType_t
(which is defined as uint16_t
) before doing the operation. That results in an overflow of the TickType_t
, which lost all the unsigned long
data (almost all data, until 65535 is all ok) before operating it to convert it to TickType_t
and use it on vTaskDelay()
function.
My thoughs was the brackets of (ms)
should be over the entire operation, like this (TickType_t) (ms / portTICK_PERIOD_MS)
for it to work properly. I do the operation on my code, and use vTaskDelay()
instead of delay()
, and it worked as expected, for 300000 ms
I had a 5 minutes delay.
So I raise this issue to inform, what I supose is a typo error, this library error.
I don't belive that someone else are going to use a 5 minutes delay, but I used and found this error.
I don't speak English natively, so I used Google Translate to help me write.
Thanks for this great work.
I would like to use FreeRTOS library with lgt8f328p from LogicGreen. Is this micro supported by chance?
thanks a lot.
hi, i was try make some project include String data, but it's not working.....
Hi Phillip,
I just stumbled upon the return type of uxTaskGetStackHighWaterMark()
: It's UBaseType_t
, and that is defined as unsigned char
in this port. The stack size is provided as unsigned short
words to xTaskCreate(), thus theoretically 64kB are possible here.
Wouldn't it be better to patch tasks.c
to make it return unsigned short
instead of UBaseType_t
, as prvTaskCheckFreeStackSpace()
correctly returns a uint16_t
? Otherwise uxTaskGetStackHighWaterMark()
will return a misguiding value.
Thanks,
Flössie
I can't seem to get a string variable printed to monitor when using FreeRTOS. works fine in regular wiring language.
e.g. from analogread_digitalread example:
only blanks print to screen
for (;;)
{
// read the input on analog pin 0:
String sensorValue = String(analogRead(A0));
// See if we can obtain or "Take" the Serial Semaphore.
// If the semaphore is not available, wait 5 ticks of the Scheduler to see if it becomes free.
if ( xSemaphoreTake( xSerialSemaphore, ( TickType_t ) 5 ) == pdTRUE )
{
// We were able to obtain or "Take" the semaphore and can now access the shared resource.
// We want to have the Serial Port for us alone, as it takes some time to print,
// so we don't want it getting stolen during the middle of a conversion.
// print out the value you read:
Serial.println(sensorValue);
xSemaphoreGive( xSerialSemaphore ); // Now free or "Give" the Serial Port for others.
}
vTaskDelay(1); // one tick delay (15ms) in between reads for stability
}
Hi Phillip,
standard AVR board are quite limited and FreeRTOS™ certainly cannot give the best of itself on a few Kbytes SRAM board with an 8 bit MCU running at 16 MHz. :-)
I would like to ask you if will be possible to add support fo the Teensy boards using Teensyduino (Arduino IDE with Teensy core) ... with the last Teensy 4.1 we have a very powerful board running at 600MHz, with a lot or SRAM and flash memory !
If can help, here : https://github.com/tsandmann/freertos-teensy you can find already a porting for teensy boards (... for PlatformIO); maybe looking at "porting files" can be useful for you to implement and make your library multi-architecture :-D
Thanks a lot in advance,
Sincerely,
Guglielmo
Describe the issue
I just downloaded your library and am trying to get the AnalogRead example to work. I get the following error message which I don't know how to interpret:
In file included from C:\Users\..\AppData\Local\Temp\.arduinoIDE-unsaved20221122-7040-5ioosa.bgo\AnalogRead_DigitalRead\AnalogRead_DigitalRead.ino:1:
c:\Users\..\Documents\Arduino\libraries\FreeRTOS\src/Arduino_FreeRTOS.h:133:10: error: #error INCLUDE_vTaskDelayUntil and INCLUDE_xTaskDelayUntil are both defined. INCLUDE_vTaskDelayUntil is no longer required and should be removed
#error INCLUDE_vTaskDelayUntil and INCLUDE_xTaskDelayUntil are both defined. INCLUDE_vTaskDelayUntil is no longer required and should be removed
^~~~~
In file included from c:\Users\..\Documents\Arduino\libraries\FreeRTOS\src/Arduino_FreeRTOS.h:1365,
from C:\Users\..\AppData\Local\Temp\.arduinoIDE-unsaved20221122-7040-5ioosa.bgo\AnalogRead_DigitalRead\AnalogRead_DigitalRead.ino:1:
c:\Users\..\Documents\Arduino\libraries\FreeRTOS\src/FreeRTOSVariant.h:33:10: fatal error: avr/io.h: No such file or directory
#include <avr/io.h>
^~~~~~~~~~
compilation terminated.
exit status 1
Compilation error: exit status 1
Expected behavior
A clear and concise description of what you expected to happen.
Screenshots
If applicable, add screenshots to help explain your problem.
Desktop (please complete the following information):
Additional context
Add any other context about the problem here.
https://github.com/feilipu/Arduino_FreeRTOS_Library
https://github.com/feilipu/miniAVRfreeRTOS
https://github.com/feilipu/avrfreertos
and the original rtos kernel avr ports https://www.freertos.org/a00098.html ?
Hi! I started a thread at:
https://sourceforge.net/p/freertos/discussion/382005/thread/3d6c0636/ Because the credits for this user contributed library in Arduino was giving credit to Richard Barry. Any way... Long story short... I'm hoping you can help me!
I'm trying to slip FreeRTOS under Marlin (the 3D Printing firmware) and have run into a problem. I want to keep trying to xCreateTask() with decreasing amounts of stack memory until the task starts successfully. In order to do that, I need configUSE_MALLOC_FAILED_HOOK=0 (or else the malloc() routines will lock up with the board's LED blinking).
I can't do that because vTaskStartScheduler() makes a call to vApplicationMallocFailedHook();
Can we make a small change in the release version of Arduino's FreeRTOS as described below? It is easy enough to make the change, but the distribution of the needed change is difficult. Marlin uses the GNU license and it would be messy for us to distribute a modified version of FreeRTOS.
void initVariant(void)
{
#if defined(USBCON)
USBDevice.attach();
#endif
setup(); // the normal Arduino setup() function is run here.
vTaskStartScheduler(); // initialise and run the freeRTOS scheduler. Execution should never return here.
#if ( configUSE_MALLOC_FAILED_HOOK == 1 )
vApplicationMallocFailedHook(); // Probably we've failed trying to initialise heap for the scheduler. Let someone know.
#endif
HANG: goto HANG;
return;
}
Hello,
i was wondering if it would make sense to include support for the arduino due in this freertos port. Since it is one of the higher sophisticated boards from arduino it would be totally reasonable to have a freertos running on it. Unfortunately there aren't that much port available and if they are quite outdated and doesn't work that well without deep diving into freertos itself. (e.g. https://github.com/bdmihai/DueFreeRTOS)
Previously i used your port on my megas which run perfectly fine but due to hardware limitations iam forced to switch to a higher performant board which in that case is the due until the giga (an absolute monster imo for hobbyists) support is coming around.
I do lack the necessary time to create a port myself which iam not at all familiar with but overall it would be a really nice addition to support that board in this library aswell.
Is it planned in the nearer future or are there quite some limitations for it except of course the time that can be scheduled onto this project.
Describe the issue
delay() function stops the code from continuing.
Sample code:
=================================================================
#include <Arduino_FreeRTOS.h>
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(115200);
delay(1000);
Serial.println("Setup starts."); // This wont execute anymore.
}
void loop()
{
// Empty. Things are done in Tasks.
}
=================================================================
Expected behavior
"Setup starts." should be displayed on the serial monitor.
Desktop (please complete the following information):
The documentation is a little unclear about how to upgrade to the latest FreeRTOS version. The links take us to the FreeRTOS page, but what then? Do we just overlay the FreeRTOS files over the Arduino_FreeRTOS src and rebuild? Does Arduino_FreeRTOS test new versions of FreeRTOS?
Having a couple of paragraphs on this would be very helpful.
Hi Phillip,
thanks a lot for your FreeRTOS port to Arduino. It's a pleasure to use and works as expected. 👍
To save some SRAM and for being able to see SRAM usage when compiling, I'd like use the static create()
variants for tasks, counting semaphores, and mutexes. I've done a five minutes modification to your sources and reached the point where the linker can't find the pxCurrentTCB
instance. What I did was:
#define configSUPPORT_STATIC_ALLOCATION 1
in FreeRTOSConfig.h
#include "FreeRTOSVariant.h"
to the end of Arduino_FreeRTOS.h
#define configUSE_TIMERS 0
in FreeRTOSConfig.h
vApplicationGetIdleTaskMemory()
variant hookNow I'm stuck. If you have some time looking into it, that would be highly appreciated. 😄
Best,
Flössie
PS: Why enable configUSE_TIMERS
when one can do the same with a task? Doesn't that take away SRAM unnecessarily? And why spend 8 bytes on the task name, when there's no pratical use for it?
Describe the issue
Since Release 10.4.6-3, the Arduino delay()
function doesn't do a busy wait anymore. This broke the real-time behaviour on my Arduino Mega because it now uses vTaskDelay()
under the hood, and on the Arduino Mega, there is no real SysTick (here, the watchdog timeout with a resolution of 15 ms is used), what doesn't allow fast task changes during the FreeRTOS scheduler. Furthermore, because of the crazy oscillator, it is also not very accurate (the watchdog oscillator frequency depends (see page 392 on ATmega2560 datasheet on the voltage and the temperature). But in combination with ISRs and the direct call of taskYIELD()
if required, this works well (here, if you are interested in what we do: https://www.youtube.com/watch?v=loU-Y_Ek8XI).
Expected behavior
The delay()
function comes from the Arduino framework and not from FreeRTOS. Therefore, it shouldn't be redefined. Or, when necessary, there should be an option where it is possible to decide whether to use the new behaviour or to use the well known "busy wait" behaviour.
Additional context
I read already #113 and RalphBacon/244-RTOS-for-Arduino#1, but I think redefining well-understood functions from a non-sleep blocking busy wait to a sleep blocking behaviour which breaks the real-time behaviour---where I don't expect changes---should be done very carefully.
Maybe we can discuss about that?
Array Queue is missing in Example
I have been trying to keep up to date on these releases but something is acting against me.
When I try to update it keeps installing 8.2.3, instead of 8.2.3-xx.
This screenshot shows what it looks like:
[(https://www.dropbox.com/s/gh2h3q2yxs7nen5/Screenshot%202016-09-19%2014.52.06.png?dl=0)]
I try to catch it when I perform updates to the rest of the libraries and skip that one, but I miss it sometimes.
This happens on at least 3 separate windows systems.
Code:
#include <Arduino.h>
#include <Arduino_FreeRTOS.h>
void setup()
{
Serial.begin(9600);
while (!Serial)
{
;
}
Serial.print("Setup and loop task running with priority ");
Serial.println(uxTaskPriorityGet(NULL));
vTaskDelay(1000 / portTICK_PERIOD_MS);
Serial.println("OK");
}
void loop() {}
Expected (if comment out the vTaskDelay line):
Setup and loop task running with priority 32
OK
Actual output: Weird output.
Using Arduino Mega 2560
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.