Git Product home page Git Product logo

f3's Introduction

Build status crates.io crates.io

f3

Board Support Crate for the STM32F3DISCOVERY

Implementation of Madgwick's algorithm. Click to see video. Source in examples/madgwick.rs

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

f3's People

Contributors

bors[bot] avatar brandonedens avatar getreu avatar homunkulus avatar japaric avatar jonte avatar rnestler avatar tahnok 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

Watchers

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

f3's Issues

Binary size and flashing with st-flash

Hi @japaric . The binary size of blinky is around 2.6 mb. Given the flash size is 256K, how is gdb load working? Is there some sort of partial loading?

du -sh blinky
2.6M	blinky

But debug build with st-flash fails while release build works (flashing works, doesn't blink though)

st-flash write blinky  0x08000000

remove aliased mutable borrows

I have this crazy idea and maybe you can tell me if I'm mistaken. My point is: why do we need to have mutable reference to volatile register to modify it? As we are talking about hardware registers as the name of the crate implies, the value behind it should only be accessed via volatile operations, so from the end user perspective there is no difference if the value was changed by the hardware or concurrently via another shared reference (for some hardware the value in register can be changed by simply reading the register). This requirement to have mutable reference does not give any guarantees or safety in any way.
So I propose to lift this restriction in volatile register crate and to use only immutable shared references to access the register structs. This will simplify the code considerably and remove this unsafe dance with aliased mutable borrows.

split memory map into its own crate

That should improve recompilation times of this crate (both as a lib and its examples).

And if we get some easy way to build dependencies in release mode while the top crate is still compiled in debug mode, that should improve a lot run time of examples compiled in debug mode.

Unable to run madgwick/viz demo

I am having some trouble running the madgwick example with the viz demo. I am attempting to use ITM over the USB port so I have uncommented the following in my .gdbinit:

monitor tpiu config internal itm.fifo uart off 64000000
monitor itm port 0 on

I have also added a jumper between PB3 and SWD. To test this setup, I did run the itm example, which does work as long as I change the 64000000 above to 8000000.

When I run itmdump -F -f /tmp/itm.fifo I either get nothing, which is surprising to me, or I get jumbled text, which I think would be expected given how the data is encoded?

But then when I run itmdump -F -f /tmp/itm.fifo | cargo run within the viz directory (I added a .cargo/config to target my machine in the viz directory so I can run this from within the f3 project), I either get the GUI showing up but the square just renders in the initial position and doesn't move at all, or I get an instant crash with the error end of file during packet.

I did try originally to set this up using a UART to USB adapter, but I ran into some trouble when trying to configure the adapter:

Joshs-MBP:viz josh$ stty -F /dev/tty.usbserial-AC01X6VL raw 2000000 -echo
stty: illegal option -- -F
usage: stty [-a|-e|-g] [-f file] [options]
Joshs-MBP:viz josh$ stty -f /dev/tty.usbserial-AC01X6VL raw 2000000 -echo
stty: tcsetattr: Invalid argument

I am on OSX, if that matters. Are there other requirements necessary to run this that I've missed?

Example failing to link with 1.30.0-nightly (2018-09-13)

This is also the case with cortex-m-rt examples.

I get a linking error:

cargo build --example blinky --target thumbv7em-none-eabihf
   Compiling f3 v0.6.1 (file:///home/nicodemus/src/nicodemus26/f3)             
^Merror: linking with `rust-lld` failed: exit code: 1
  |
  = note: "rust-lld" "-flavor" "gnu" "-L" "/home/nicodemus/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/thumbv7em-none-eabihf/lib" 
...
 "-Wl,-Tlink.x" "-nostartfiles" "-Bdynamic"
  = note: rust-lld: error: unknown argument: -Wl,-Tlink.x
          rust-lld: error: unknown argument: -nostartfiles

Running with arm-none-eabi-gdb (and gdb) from gcc-arm-none-eabi-7-2018-q2.

I can comment the linker flags from .cargo/config and the build succeeds, but I get the following error from gdb when running:

Reading symbols from target/thumbv7em-none-eabihf/debug/examples/blinky...done.
0x00000000 in ?? ()
semihosting is enabled
Start address 0x0, load size 0
Transfer rate: 0 bits in <1 sec.
.gdbinit:18: Error in sourced command file:
Cannot find bounds of current function
(gdb) 

where .gdbinit:18 is the step after load.

Start address 0x0, load size 0 suggest to me that the load is failing silently.

The binary itself is about 2Mb:

ls target/thumbv7em-none-eabihf/debug/examples/blinky -la
-rwxrwxr-x 2 nicodemus nicodemus 2016448 Sep 14 15:04 target/thumbv7em-none-eabihf/debug/examples/blinky

My board uses STlinkV2, not 2-1

Hello. Great thanks to you, japaric. Finally I can forget horrible C and write hight-level code with my favorite programming language. Finally there is direct and safe way how to use this fantastic MCU. Finally I can use one language for all my projects and platforms! Your Discovery book is pretty good, so detailed and neat as I prefer. You've done great work.

But where are some problems with your Discovery book:

  1. rename pg to f3, I guess =)
  2. My board uses STLinkV2, so I used this udev rule
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", \
    MODE:="0666", \
    SYMLINK+="stlinkv2_%n", \
    GROUP:="uucp"

STLinkV2's ATTRS{idProduct} must be 3748, not 374b.
Otherwise I have root user of /dev/bus/usb// because this rule do not accept current board.

That is all at the moment.

UDP. Your book has no link to http://www.st.com/content/ccc/resource/technical/document/reference_manual/4a/19/6e/18/9d/92/43/32/DM00043574.pdf/files/DM00043574.pdf/jcr:content/translations/en.DM00043574.pdf It has only link to discovery datascheet

Version 0.5.0 not release to Crates.io

Hi.

I wanted to test some of the examples from this crate. I followed the cortex-m-quickstart setup, making sure to follow the f3 guide removing the correct stuff to get it to work. However, I could not get my code to compile. I see that many dependencies have been updated and the f3 crate version on github has been updated, but this latest version is not on crates.io.

Is this deliberate or a quick oversight?

opt-out Cargo feature to not initialize .bss / .data

Some applications don't use these sections. They should be able to opt-out of the initialization code that zeroes .bss and initializes .data.

When this Cargo feature is disabled, use of static mut variables, or rather anything that goes in these sections, should be forbidden via linker script magic.

Question: How to handle `EXTI` interrupts

I have started testing some interrupt handling from the built in l3gd20 and gotten it half way to work. However, I don't quite understand how to process the interrupt and stop the line from continuing to be high. I have tested with the following simple example:

//! This example uses the [Real Time For the Masses framework](https://docs.rs/cortex-m-rtfm/~0.3)
#![deny(warnings)]
#![feature(proc_macro)]
#![no_std]

extern crate cortex_m;
extern crate cortex_m_rtfm as rtfm;
extern crate f3;

use cortex_m::asm;
use f3::hal::prelude::*;
use f3::hal::spi::Spi;
use f3::hal::stm32f30x;
use f3::{L3gd20, l3gd20};
use rtfm::{app, Threshold};

app! {
    device: stm32f30x,

    resources: {
        static GYRO: L3gd20;
        static COUNT: usize = 0;
    },

    tasks: {
        EXTI1: {
            path: sensor_interrupt,
            resources: [GYRO, COUNT],
        }
    },
}

fn init(p: init::Peripherals, _: init::Resources) -> init::LateResources {
    let mut flash = p.device.FLASH.constrain();
    // Enable SYSCFG so that we can change EXTI pin configuration (see below)
    p.device.RCC.apb2enr.write(|w| w.syscfgen().enabled());
    let mut rcc = p.device.RCC.constrain();

    let clocks = rcc.cfgr.freeze(&mut flash.acr);
    let mut gpioa = p.device.GPIOA.split(&mut rcc.ahb);
    let mut gpioe = p.device.GPIOE.split(&mut rcc.ahb);

    let mut nss = gpioe
        .pe3
        .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper);
    nss.set_high();

    // The `L3gd20` abstraction exposed by the `f3` crate requires a specific pin configuration to
    // be used and won't accept any configuration other than the one used here. Trying to use a
    // different pin configuration will result in a compiler error.
    let sck = gpioa.pa5.into_af5(&mut gpioa.moder, &mut gpioa.afrl);
    let miso = gpioa.pa6.into_af5(&mut gpioa.moder, &mut gpioa.afrl);
    let mosi = gpioa.pa7.into_af5(&mut gpioa.moder, &mut gpioa.afrl);

    let spi = Spi::spi1(
        p.device.SPI1,
        (sck, miso, mosi),
        l3gd20::MODE,
        1.mhz(),
        clocks,
        &mut rcc.apb2,
    );

    // Setup interrupt from sensor. The first thing to do is to change EXIT1
    // configuration to trap on pin `E`
    p.device.SYSCFG.exticr1.write(|w| unsafe {
        w.exti1().bits(0x04)
    });
    // Configure EXTI1 to enable interrupts
    //p.device.EXTI.emr1.write(|w| w.mr1().set_bit());
    p.device.EXTI.imr1.write(|w| w.mr1().set_bit());
    //p.device.EXTI.ftsr1.write(|w| w.tr1().set_bit());
    p.device.EXTI.rtsr1.write(|w| w.tr1().set_bit());

    let mut l3gd20 = L3gd20::new(spi, nss).unwrap();
    l3gd20.drdy_interrupt(true).unwrap();

    // Need to read gyro to enable interrupt?
    l3gd20.gyro().unwrap();

    init::LateResources {
        GYRO: l3gd20,
    }
}

fn idle() -> ! {
    // Sleep
    loop {
        rtfm::wfi();
    }
}

fn sensor_interrupt(_: &mut Threshold, mut r: EXTI1::Resources) {
    let status = r.GYRO.status().unwrap();
    let _g = r.GYRO.gyro().unwrap();
    if !status.new_data {
        let _c = *r.COUNT;
        asm::bkpt();
    } else {
        *r.COUNT += 1;
    }
}

With this simple addition to the l3gd20 crate:

/// Enable or disable interrupt on `DRDY`/`INT2`
pub fn drdy_interrupt(&mut self, enable: bool) -> Result<&mut Self, E> {
    let bits = if enable { 1 << 3 } else { 0 };
    let mask = 0b0000_1000;
    self.change_config(Register::CTRL_REG3, mask, bits)
}

My question is, how do I mark the interrupt as processed in the sensor_interrupt so that the function is not called continuous?

Use board as USB device

In the user manual for the discovery board, it claims it can be used as a USB HID device.

The STM32F303VCT6 MCU is also used to drive the second USB Mini-B connector (USB USER), which allows the board to be used as a USB Device. The STM32F3DISCOVERY can then act as a USB joystick, mouse, or other similar device. If both USBs are connected, diodes D4 and D5 protect the board and use the power from the USB ST-LINK.The board can be powered through this USB USER connector, then LED1 PWR lights, LED2 COM blinks and it can run an application in standalone mode.

Does f3 support this? I can't find anything in the cortex-m, stm32f3x or hal crates related to using the MCU's HID capabilities.

opt-out Cargo feature to disable interrupts

Some applications make no use of interrupts. These should be able to remove the part of the vector table that holds the interrupt handlers.

When this Cargo feature is disabled there should be no way to declare an interrupt handler.

Async IO

As a first experiment: Future::poll based and interrupt free.

The unresolved question is how to make the microcontroller sleep? I usually use wfi when there's nothing to do but that will block forever if no interrupts are being used.

review ABI of "extern" functions

Interrupts and Exceptions must use the C ABI (or the AAPCS one? I think there's no difference between the two when the function takes no arguments).

Everything else can be extern "Rust". I think there's no advantage for using extern "Rust" right now but at least we should be able to change all those pub extern "C" fn main() -> ! to just pub fn main() -> !.

main function not linked to the binary

Hello. I'm new to this low level stuff and Rust, but thanks to your very good book Discovery, I hope to learn it.

I try to follow this book, and everything was ok until I tried to set the break point on function main() (Chapter 5).
My problem is that the gdb says that there is no main() function in my code. And obj-dump confirms that there is no such function.
I guess that since there is no reference to this function it was simply omitted.

I would expect that the file stm32f3discovery.ld will contain declaration with the main() but there is only _init().

Here is the contents of my stm32f3discovery.ld:

MEMORY
{
  CCRAM : ORIGIN = 0x10000000, LENGTH = 8K
  FLASH : ORIGIN = 0x08000000, LENGTH = 256K
  RAM : ORIGIN = 0x20000000, LENGTH = 40K
}

ENTRY(_reset)

SECTIONS
{
  .text ORIGIN(FLASH) :
  {
    /* Vector table */
    LONG(ORIGIN(RAM) + LENGTH(RAM));
    LONG(_reset + 1);
    KEEP(*(.rodata._EXCEPTIONS));
    _eexceptions = .;
    /* Entry point: reset handler */
    _reset = .;
    *(.text._reset);

    *(.text.*);
    *(.rodata.*);
  } > FLASH
  /DISCARD/ :
  {
    *(.ARM.exidx.*)
    *(.bss.*)
    *(.data.*)
  }
}

/* HACK to make these symbols overrideable by _dependencies_ (they were
   already overridable by the top crate), we declare them as undefined
   (EXTERN) here. */
EXTERN(__aeabi_memclr4);
EXTERN(_default_exception_handler);
EXTERN(_init);

/* Exceptions */
PROVIDE(_nmi = _default_exception_handler);
PROVIDE(_hard_fault = _default_exception_handler);
PROVIDE(_memmanage_fault = _default_exception_handler);
PROVIDE(_bus_fault = _default_exception_handler);
PROVIDE(_usage_fault = _default_exception_handler);
PROVIDE(_svcall = _default_exception_handler);
PROVIDE(_pendsv = _default_exception_handler);
PROVIDE(_systick = _default_exception_handler);
ASSERT(_eexceptions - ORIGIN(FLASH) == 0x40, "exceptions not linked where expected");

If I add EXTERN(main); after _init, then main() is executed but _init() doesn't.
Shouldn't this script contain main() function?
Or any tips what I'm missing here?

My system: Ubuntu 16.10, Rust 1.17.0, board STM32F3Discovery.

Thank you for your great work!

upgrade to RTFM v0.2

Hello Jorge,

I like your new API version 2 a lot and I wanted to it try out with my STM32F3discovery board.
It seems that this crate is outdated. Do you plan to upgrade?

Support for naze32 flight controller

Hi @japaric. I'm pretty new to rust on microcontrollers. A lot of flight controllers seem to be using STM processors. Does this repo target flight controllers like naze32 too (STM32F103CB) ?

https://www.aliexpress.com/item/NAZE32-REV6-MPU6050-32-bit-6-DOF-10-DOF-Flight-Controller-for-Multicopter-RC-Radio-Control/32649546407.html?spm=2114.30010308.3.94.wRiZWs&ws_ab_test=searchweb0_0,searchweb201602_2,searchweb201603_1&btsid=c352ae82-e4b5-42dc-9332-df00e5bbb71a

Rust for writing flight controller code sounds very exciting to me :)

Board support crate naming could be more specific?

While short and clear names are nice, pretty and usually the way to go, I have the impression that in the case of board support crates it can cause some confusion, and it might be better to name them after the specific board they support: f3 -> stm32f3discovery

For example, while the device crate stm32f30x is clearly meant for a specific family of devices, the board support crate f3 is used for a single board, but because it's name is less specific it could be interpreted as a device crate for all f3 devices (stm32f3x) or as a board support crate for all Discovery f3 boards (of which there are two now).

There is already an f4 crate as well, which supports the 32f429idiscovery board instead of the more likely stm32f4discovery. What should a crate for that board be called? Or for the other f4 Discovery boards (of which there are six now)?

PS. Thanks for all your hard work towards realizing the dream of Rust on embedded, and especially for doing so in a nice, clean, modular and well documented way! ๐Ÿ‘

OpenOCD and GDB keep failing randomly during debug sessions

After running the "concurrency" example, the STLink communication gets unstable. The only way to connect is keeping the reset button hold while starting openocd. As soon as I release reset the connection breaks down:

Polling target stm32f3x.cpu failed, trying to reexamine
Examination failed, GDB will be halted. Polling again in 6300ms
Info : Previous state query failed, trying to reconnect  
Error: jtag status contains invalid mode value - communication failure

A similar symptom and its solution is described here:
Error: jtag status contains invalid mode value โ€“ communication failure = SOLVED! โ€“ Jara's Spare Time Electronics

Finally I found this message in a discussion forum. The problem is in the low-power mode! When CPUcore clock is halted the debugger connection fails and debug session is halted.

I am using low-power mode to halt CPU clock when OS is idle โ€“ in vApplicationIdleHook() function I have the __WFI() โ€“ wait for interrupt โ€“ intrinsic function.

DBGMCU_Config(DBGMCU_SLEEP \| DBGMCU_STOP \| DBGMCU_STANDBY, ENABLE);
-- | --

run example: error[E0432]: unresolved import `cortex_m_0_6::peripheral::itm`

Hi,

I am new for rust and when I run the example, I got this error:

cargo run --example hello
Updating git://crates.rustcc.com/crates.io-index index
Downloaded cobs v0.1.4 (registry git://crates.rustcc.com/crates.io-index)
Downloaded cortex-m-semihosting v0.3.7 (registry git://crates.rustcc.com/crates.io-index)
Downloaded madgwick v0.1.1 (registry git://crates.rustcc.com/crates.io-index)
Downloaded mat v0.2.0 (registry git://crates.rustcc.com/crates.io-index)
Downloaded panic-semihosting v0.5.6 (registry git://crates.rustcc.com/crates.io-index)
Downloaded 5 crates (860.0 KB) in 7.82s
Compiling typenum v1.12.0
Compiling semver-parser v0.7.0
Compiling nb v1.0.0
Compiling void v1.0.2
Compiling cortex-m v0.7.1
Compiling version_check v0.9.2
Compiling proc-macro2 v1.0.24
Compiling vcell v0.1.3
Compiling bitfield v0.13.2
Compiling unicode-xid v0.2.1
Compiling syn v1.0.60
Compiling stable_deref_trait v1.2.0
Compiling cortex-m v0.6.6
Compiling cortex-m-rt v0.6.13
Compiling cortex-m v0.5.10
Compiling aligned v0.2.0
Compiling stm32f30x v0.7.1
Compiling r0 v0.2.2
Compiling cortex-m-semihosting v0.3.7
Compiling f3 v0.6.1 (/Users/ccui/CLionProjects/f3)
Compiling m v0.1.1
Compiling cobs v0.1.4
Compiling byteorder v1.4.2
Compiling volatile-register v0.2.0
Compiling nb v0.1.3
Compiling semver v0.9.0
Compiling generic-array v0.14.4
Compiling embedded-hal v0.2.4
Compiling rustc_version v0.2.3
Compiling bare-metal v0.2.5
Compiling cast v0.2.3
Compiling quote v1.0.8
Compiling generic-array v0.13.2
Compiling generic-array v0.12.3
Compiling generic-array v0.11.1
Compiling mat v0.2.0
Compiling l3gd20 v0.2.0
Compiling madgwick v0.1.1
Compiling as-slice v0.1.4
Compiling aligned v0.3.4
Compiling panic-semihosting v0.5.6
error[E0432]: unresolved import cortex_m_0_6::peripheral::itm
--> /Users/ccui/.cargo/registry/src/crates.rustcc.com-a21e0f92747beca3/cortex-m-0.5.10/src/peripheral/mod.rs:91:46
|
91 | pub use cortex_m_0_6::peripheral::{cbp, fpb, itm, tpiu};
| ^^^ no itm in peripheral

error: aborting due to previous error

For more information about this error, try rustc --explain E0432.
error: could not compile cortex-m

To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: build failed

I use macbook pro with m1 CPU, could you please help me?

Thank you very much!

the led roulette example misbehaves when compiled in release mode (+LTO)

For example, this variation of the original example:

#[export_name = "main"]
pub extern "C" fn main() -> ! {
    loop {
        for led in LEDS.iter() {
            led.on();
            delay::ms(100);
            led.off();
            delay::ms(100);
        }
    }
}

when compiled in debug mode, produces the expected result: all the LEDs light on in a circular cycle.

But if the code is compiled in release mode, then only three, the "first" three, LEDs participate in the "circular" cycle.

This is the only example that misbehaves when compiled in release mode. It also happens to be only example that uses interrupts so perhaps that's the cause of the problem.

Building fails with: error[E0557]: feature has been removed

relevant output of trying to run cargo build --example hello:

error[E0557]: feature has been removed
--> /home/frederik/.cargo/registry/src/github.com-1ecc6299db9ec823/panic-semihosting-0.3.0/src/lib.rs:59:12
|
59 | #![feature(panic_implementation)]
| ^^^^^^^^^^^^^^^^^^^^
|
note: subsumed by #[panic_handler]
--> /home/frederik/.cargo/registry/src/github.com-1ecc6299db9ec823/panic-semihosting-0.3.0/src/lib.rs:59:12
|
59 | #![feature(panic_implementation)]
| ^^^^^^^^^^^^^^^^^^^^

error[E0658]: The attribute panic_implementation is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> /home/frederik/.cargo/registry/src/github.com-1ecc6299db9ec823/panic-semihosting-0.3.0/src/lib.rs:71:3
|
71 | #[panic_implementation]
| ^^^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable

Examples fail to build

$ cargo build --examples
   Compiling f3 v0.6.1 (/Users/rubberduck/src/f3)
error: use of deprecated item 'hal::prelude::_embedded_hal_digital_OutputPin::set_low': Deprecated because the methods cannot return errors. Users should use the traits in digital::v2.
   --> src/led.rs:168:18
    |
168 |         self.pex.set_low()
    |                  ^^^^^^^
    |
note: lint level defined here
   --> src/lib.rs:40:9
    |
40  | #![deny(warnings)]
    |         ^^^^^^^^
    = note: `#[deny(deprecated)]` implied by `#[deny(warnings)]`

error: use of deprecated item 'hal::prelude::_embedded_hal_digital_OutputPin::set_high': Deprecated because the methods cannot return errors. Users should use the traits in digital::v2.
   --> src/led.rs:173:18
    |
173 |         self.pex.set_high()
    |                  ^^^^^^^^

error: aborting due to 2 previous errors

error: could not compile `f3`.

To learn more, run the command again with --verbose.

unsupported relocation on symbol

Hi Jorge,

First up thanks for all the great embedded rust work you've done. I've been working though the process to create a crate f0 akin to this one but for Cortex-M0 generated by svd2rust. When compiling I get:

LLVM ERROR: unsupported relocation on symbol

It's triggered by default_handler_entry_point, specifically the branch instruction. It appears I'm encountering Bug 30279. The fix was added to LLVM in r280651. I expect that this will take a while to trickle down to rustc.

I'm a bit out of my depth at this point. From what I understand I need locate the _default_exception_handler_impl symbol closer to _default_exception_handler_impl. Is there any linker script magic that can be done that might work around the issue?

timeit module

let ticks: u32 = timeit(|| iprintln!("Hello, world!"));

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.