Giter Club home page Giter Club logo

libopencm3-examples's Introduction

README

Build Status

Gitter channel

The libopencm3 project aims to create an open-source firmware library for various ARM Cortex-M microcontrollers.

Currently (at least partly) supported microcontrollers:

  • ST STM32 F0xx/F1xx/F2xx/F30x/F37x/F4xx/F7xx/H7xx series
  • ST STM32 G0xx G4xx L0xx L1xx L4xx series
  • Atmel SAM3A/3N/3S/3U/3X series, as well as SAMDxx and friends
  • NXP LPC1311/13/17/42/43
  • Stellaris LM3S series (discontinued, without replacement)
  • TI (Tiva) LM4F series (continuing as TM4F, pin and peripheral compatible)
  • EFM32 Gecko series (only core support)
  • Freescale Vybrid VF6xx
  • Qorvo (formerly ActiveSemi) PAC55XX
  • Synwit SWM050
  • Nordic NRF51x and NRF52x

The library is written completely from scratch based on the vendor datasheets, programming manuals, and application notes. The code is meant to be used with a GCC toolchain for ARM (arm-elf or arm-none-eabi), flashing of the code to a microcontroller can be done using the OpenOCD ARM JTAG software.

Status and API

The libopencm3 project is (and presumably, always will be) a work in progress. Not all subsystems of all microcontrollers are supported, yet, though some parts have more complete support than others.

Prior to version 0.8.0, the api was largely in flux. Attempts were made to provide backwards compatibility, but this was not always considered critical.

From 0.8.0 to 1.0, we'll atempt to follow semver, but EXPECT CHANGES, as we attempt to clear up old APIs and remove deprecated functions. The 0.8.0 tag was placed to provide the "old stable" point before all the new code started landing.

preview code often lands in the "wildwest-N" branches that appear and disappear in the repository. Pull requests marked as "merged-dev" will be in this branch, and will be closed when they merge to master. This is useful for bigger interdependent patch sets, and also allows review of merge conflicts in public.

From 1.0, expect to follow semver, with functions (and defines!) being deprecated for a release before being removed.

TIP: Include this repository as a Git submodule in your project to make sure your users get the right version of the library to compile your project. For how that can be done refer to the libopencm3-template repository.

Prerequisites

Building requires Python (some code is generated).

For Ubuntu/Fedora:

  • An arm-none-eabi/arm-elf toolchain.

For Windows:

Download and install:

Run msys shell and set the path without standard Windows paths (adjusting to your version of Python), so Windows programs such as 'find' won't interfere:

export PATH="/c//Program Files/Python 3.9:/c/ARMToolchain/bin:/usr/local/bin:/usr/bin:/bin"

After that you can navigate to the folder where you've extracted libopencm3 and build it.

Toolchain

The most heavily tested toolchain is "gcc-arm-embedded" This used to be available at https://launchpad.net/gcc-arm-embedded

Other toolchains should work, but they have not been nearly as well tested. Toolchains targeting Linux, such as "gcc-arm-linux-gnu" or the like are not appropriate.

NOTE: GCC version 6 or later is required, as we're using attributes on enumerators to help mark deprecations.

Building

$ make

If you have an arm-elf toolchain (uncommon) you may want to override the toolchain prefix (arm-none-eabi is the default)

$ PREFIX=arm-elf make

For a more verbose build you can use

$ make V=1

You can reduce the build time by specifying a particular MCU series

$ make TARGETS='stm32/f1 stm32/f4'

Supported targets can be listed using:

$ make list-targets

Fine-tuning the build

The build may be fine-tuned with a limited number of parameters, by specifying them as environment variables, for example:

$ VARIABLE=value make
  • FP_FLAGS - Control the floating-point ABI

    If the Cortex-M core supports a hard float ABI, it will be compiled with the best floating-point support by default. In cases where this is not desired, the behavior can be specified by setting FP_FLAGS.

    Currently, M4F cores default to -mfloat-abi=hard -mfpu=fpv4-sp-d16, and M7 cores defaults to double precision -mfloat-abi=hard -mfpu=fpv5-d16 if available, and single precision -mfloat-abi=hard -mfpu=fpv5-sp-d16 otherwise. Other architectures use no FP flags, in otherwords, traditional softfp.

    You may find which FP_FLAGS you can use in a particular architecture in the readme.txt file shipped with the gcc-arm-embedded package.

    Examples:

      $ FP_FLAGS="-mfloat-abi=soft" make               # No hardfloat
      $ FP_FLAGS="-mfloat-abi=hard -mfpu=magic" make   # New FPU we don't know of
    
  • CFLAGS - Add to or supersede compiler flags

    If the library needs to be compiled with additional flags, they can be passed to the build system via the environment variable CFLAGS. The contents of CFLAGS will be placed after all flags defined by the build system, giving the user a way to override any default if necessary.

    Examples:

      $ CFLAGS="-fshort-wchar" make    # Compile lib with 2 byte wide wchar_t
    

Example projects

The libopencm3 community has written and is maintaining a huge collection of examples, displaying the capabilities and uses of the library. You can find all of them in the libopencm3-examples repository:

https://github.com/libopencm3/libopencm3-examples

If you just wish to test your toolchain and build environment, a collection of mini blink projects is available too. This covers many more boards, but, as the name suggests, only demonstrates blinking LEDs.

https://github.com/libopencm3/libopencm3-miniblink

Installation

Simply pass -I and -L flags to your own project. See the libopencm3-template repository for a template repository using this library as a Git submodule, the most popular method of use. The libopencm3-examples is another example of this.

It is strongly advised that you do not attempt to install this library to any path inside your toolchain itself. While this means you don't have to include any -I or -L flags in your projects, it is very easy to confuse a multi-library linker from picking the right versions of libraries. Common symptoms are hardfaults caused by branches into ARM code. You can use arm-none-eabi-objdump to check for this in your final ELF file. You have been warned.

Coding style and development guidelines

See HACKING.

License

The libopencm3 code is released under the terms of the GNU Lesser General Public License (LGPL), version 3 or later.

See COPYING.GPL3 and COPYING.LGPL3 for details.

Community

  • Our Gitter channel
  • Our IRC channel on the libera.chat IRC network is called #libopencm3

Mailing lists

Website

libopencm3-examples's People

Contributors

agners avatar alios avatar bufran avatar cat-ion avatar chuckm avatar daniel-thompson avatar esden avatar fb avatar garag avatar jelmert avatar jkent avatar karlp avatar kbob avatar l29ah avatar leighbb avatar lifton avatar loldgit avatar materi avatar millerd avatar mrnuke avatar onnokort avatar paulfertser avatar petermortensen avatar plaes avatar prusnak avatar rohieb avatar schodet avatar spiccinini avatar twoerner avatar uwebonnes 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

libopencm3-examples's Issues

lpc43xx hackrf i2c demo fails to compile

I've got no idea what's wrong, or when, and I'm not super interested personally, as I don't have any hardware. But I'd like to enable the lpc43xx directory for building. Can't/won't do that until the examples build at least :)

Further, they all produce warnings about some ram_local2 memory section?

stm32f429i-discovery/sdram not working

I built and flashed the stm32f429i-discovery/sdram demo.

I get a mass storage device showing up and it auto-mounts as vfat on Fedora 23. But if I try to do anything like cat or head on the datafile the I see on the drive I get an IO error.

USB CDC example for stellaris-ek-lm4f120xl not working under WinXP/Win7

Hello,
i have tested the cdc example for the stellaris-ek-lm4f120xl board under Windows. When i plug USB the device gets enumerated (with a patched inf file) and all seems good. But when i try to open the device with a terminal program i am getting an error.

The Problem seems to be a USB_CDC_REQ_SET_LINE_CODING with databits set to 0. As this is invalid the function cdcacm_control_request() returns 0 and the transfer will be stalled.

So i am unsure how to handle the bad USB_CDC_REQ_SET_LINE_CODING request. Maybe ignore the bad databits setting return with no error.

If desired i can make a pull request.

If there is an spi_init_master, there should be an spi_init_slave.

I have added spi_init_slave.

The change looks straightforward and should work. But it's untested, will move on to testing this shortly. Hmmm.... We could remove the baud rate parameter in the _init_slave call. ok, we SHOULD remove.... Done.

I renamed the "br" parameter to "baud" because "br" confused me for a split second.

cat ../../spi_init_slave.patch
diff --git a/include/libopencm3/stm32/common/spi_common_all.h b/include/libopencm3/stm32/common/spi_common_all.h
index fa4affb..a77fcbf 100644
--- a/include/libopencm3/stm32/common/spi_common_all.h
+++ b/include/libopencm3/stm32/common/spi_common_all.h
@@ -386,7 +386,9 @@ specific memorymap.h header before including this header file.*/
 BEGIN_DECLS

 void spi_reset(uint32_t spi_peripheral);
-int spi_init_master(uint32_t spi, uint32_t br, uint32_t cpol, uint32_t cpha,
+int spi_init_master(uint32_t spi, uint32_t baud, uint32_t cpol, uint32_t cpha,
+                   uint32_t dff, uint32_t lsbfirst);
+int spi_init_slave(uint32_t spi, uint32_t cpol, uint32_t cpha,
                    uint32_t dff, uint32_t lsbfirst);
 void spi_enable(uint32_t spi);
 void spi_disable(uint32_t spi);
diff --git a/lib/stm32/common/spi_common_f03.c b/lib/stm32/common/spi_common_f03.c
index 5713653..486bd48 100644
--- a/lib/stm32/common/spi_common_f03.c
+++ b/lib/stm32/common/spi_common_f03.c
@@ -89,17 +89,17 @@ spi_lsbfirst.
 @returns int. Error code.
 */

-int spi_init_master(uint32_t spi, uint32_t br, uint32_t cpol, uint32_t cpha,
-                   uint32_t crcl, uint32_t lsbfirst)
+int spi_init_master_slave (uint32_t spi, uint32_t baud, uint32_t cpol, uint32_t cpha,
+                          uint32_t crcl, uint32_t lsbfirst, uint32_t master)
 {
        uint32_t reg32 = SPI_CR1(spi);

        /* Reset all bits omitting SPE, CRCEN and CRCNEXT bits. */
        reg32 &= SPI_CR1_SPE | SPI_CR1_CRCEN | SPI_CR1_CRCNEXT;

-       reg32 |= SPI_CR1_MSTR;  /* Configure SPI as master. */
+       reg32 |= master;        /* Configure SPI as master. */

-       reg32 |= br;            /* Set baud rate bits. */
+       reg32 |= baud;          /* Set baud rate bits. */
        reg32 |= cpol;          /* Set CPOL value. */
        reg32 |= cpha;          /* Set CPHA value. */
        reg32 |= crcl;          /* Set crc length (8 or 16 bits). */
@@ -112,6 +112,20 @@ int spi_init_master(uint32_t spi, uint32_t br, uint32_t cpol, uint32_t cpha,
        return 0; /* TODO */
 }

+int spi_init_master(uint32_t spi, uint32_t baud, uint32_t cpol, uint32_t cpha,
+                    uint32_t dff, uint32_t lsbfirst)
+{
+       return spi_init_master_slave(spi, baud, cpol, cpha, dff, lsbfirst, SPI_CR1_MSTR);
+}
+
+
+int spi_init_slave(uint32_t spi, uint32_t cpol, uint32_t cpha,
+                   uint32_t dff, uint32_t lsbfirst)
+{
+       return spi_init_master_slave(spi, 0, cpol, cpha, dff, lsbfirst, 0); // maybe we should have a define for SLAVE
+}
+
+
 void spi_send8(uint32_t spi, uint8_t data)
 {
        /* Wait for transfer finished. */
diff --git a/lib/stm32/common/spi_common_l1f124.c b/lib/stm32/common/spi_common_l1f124.c
index 6345350..0d05364 100644
--- a/lib/stm32/common/spi_common_l1f124.c
+++ b/lib/stm32/common/spi_common_l1f124.c
@@ -89,17 +89,17 @@ spi_lsbfirst.
 @returns int. Error code.
 */

-int spi_init_master(uint32_t spi, uint32_t br, uint32_t cpol, uint32_t cpha,
-                   uint32_t dff, uint32_t lsbfirst)
+int spi_init_master_slave(uint32_t spi, uint32_t baud, uint32_t cpol, uint32_t cpha,
+                         uint32_t dff, uint32_t lsbfirst, uint32_t master)
 {
        uint32_t reg32 = SPI_CR1(spi);

        /* Reset all bits omitting SPE, CRCEN and CRCNEXT bits. */
        reg32 &= SPI_CR1_SPE | SPI_CR1_CRCEN | SPI_CR1_CRCNEXT;

-       reg32 |= SPI_CR1_MSTR;  /* Configure SPI as master. */
+       reg32 |= master;        /* Configure SPI as master (or not). */

-       reg32 |= br;            /* Set baud rate bits. */
+       reg32 |= baud;          /* Set baud rate bits. */
        reg32 |= cpol;          /* Set CPOL value. */
        reg32 |= cpha;          /* Set CPHA value. */
        reg32 |= dff;           /* Set data format (8 or 16 bits). */
@@ -112,6 +112,21 @@ int spi_init_master(uint32_t spi, uint32_t br, uint32_t cpol, uint32_t cpha,
        return 0; /* TODO */
 }

+
+int spi_init_master(uint32_t spi, uint32_t baud, uint32_t cpol, uint32_t cpha,
+                   uint32_t dff, uint32_t lsbfirst)
+{
+       return spi_init_master_slave(spi, baud, cpol, cpha, dff, lsbfirst, SPI_CR1_MSTR);
+}
+
+
+int spi_init_slave(uint32_t spi, uint32_t cpol, uint32_t cpha,
+                  uint32_t dff, uint32_t lsbfirst)
+{
+       return spi_init_master_slave(spi, 0, cpol, cpha, dff, lsbfirst, 0); // maybe we should have a define for SLAVE
+}
+
+
 /*---------------------------------------------------------------------------*/
 /** @brief SPI Set Data Frame Format to 8 bits

Old vs new style ld scripts

There are two ways of dealing with linker scripts (very roughly):

  • Old style: static linker script. Example: defining LDSCRIPT=stm32-h103.ld in the Makefile.
  • New style: linker dynamically generated. Example: defining device=STM32F103RBT6 and including genlink-config.mk in the Makefile

libopencm3-examples seems to support both on its main Makefile (rules.mk) but most of the examples (all?) use the old style:

  • First of all, I guess the new style is the preferred way in libopencm3?
  • If so, why are the examples using the old way? Simply because no one has done? Or is it intentional? If the former, I could help porting some examples to the new style.

Thanks!

usb-cdc for maple-mini not compilng

when i tried compiling the cdc-acm project i get an error stating "stm32f103_usb_driver undeclared " in line no. 261 (cdcacm.c source file) the usbd_init function, as i tried declaring the variable of type usbd_driver which is typedef structure in usb_private.h still get error as storage size unknown.

stm32f4-discovery USB examples don't work

Hi,

I have an stm32f4-discovery board labeled MB997D which comes with STM32F407VG. I tested every example on the stm32f4-discovery directory and they all work, except for the USB examples. I didn't get my scope hooked up yet, but if I were to guess, Data Pull up isn't being connected.

I suppose the reason for data pullup to not being connected, even though we clear bit 1 in DCTL, is because the USB IP doesn't realize that VBUS is above 4.4V. Going through the datasheet, I found out that PA9 is not, anymore, used as OTG_FS_VBUS. In fact, AF10 is not a valid mux mode for GPIOA_10.

Any hints about what to do here? I actually have this same failure on two different boards (stm32f4-discovery and stm32-h405 from Olimex).

Reuse section of README is incorrect

Description of steps how to reuse libopencm3-examples build system in his own project is not proper. There also should be contained a step of copying ld_script (it's required for stm32f4_discovery at least).
It would be good idea to add basic templates of makefiles for new projects for each platforms.

stm32f429 demos descriptions are terse

I've just started diving into opencm3 and I'm pretty impressed. I quickly got a few demos built and flashed. I started with the stm32f429i-discovery which has quite a lot of good stuff.

However, I quickly got stuck because the readme's are so terse.

The top level readme has:

  1. usart_console - Program a USART on the board as a console (requires
    clonsing jumpers on your discovery board connecting USART1 to the
    programmer)

Well I guess clonsing is closing but they are already in the closed position to use the STLINK to flash the board. Did this mean open? But that does not work either. :(

The full readme for that demo says:

Simple USART Example

This example sets up a USART port and provides a few simple
character handling functions to that a short interactive program
can be demonstrated. It re-uses the clock setup from systick_blink
and that means you could do times delays but that aspect isn't used.

So what should I expect / do ?

If I get nothing is there a problem? I would not know because there is so little about what this demo is supposed to do.

In fact this whole jumper story is completely opaque, even in the ST user manual . On or off I never get a ACM device showing. There seems to be more to it but some explicit instructions are needed to get the demo to run.

Some of the readme's in the other branches are pretty good but this branch is a little too light to of much help.

Maple miniblink enables clock for GPIO C, then uses GPIO A, doesn't blink.

https://github.com/libopencm3/libopencm3-examples/blob/master/examples/stm32/f1/stm32-maple/miniblink/miniblink.c

I sed this as a test hello with a Maple Mini clone and got no output. I looked at the code and noticed that it does rcc_periph_clock_enable(RCC_GPIOC); and then wiggles GPIOA5. Changing the enable to RCC_GPIOA made the pin "blink".

There is no led on that pin on Maple, but that may or may not be the intended outcome.

lsusb shows this codes device as STM32F407?

libopencm3-examples / examples / stm32 / f1 / stm32-h103 / usb_cdcacm
is the device name string from libopencm3?
and is there a way to make windows recognise this device.
it knows it is a cdcacm device but can't find a driver?
maybe it's the device name?

readability of the external interrupt code

because of the mass of #defines (DISCO_) you have to read the sysconfig.h and the main.c at the same time. to understand the use of the external Interrupt it would be better to write the direct name in the librarys functions..

or just some comments on the interrupt functions...

stm32f4-discovery/usb_msc doesn't work

It can be recognized by Linux, and you also can read any sector you want.

But you can't write, if you write, the kernel unloads this device and report I/O error.

stm32f107/207 usbd_init hangs when RCC_OTGFS clock is not enabled

Hello!

In lib/usb/usb_f107 (and also in lib/usb/usb_f207) there are 2 while loops, and the "Wait for AHB idle" one never exits if the OTG clock is disabled. A little bit hard to understand (at least for a beginner) why the system hangs. I recommend usiing some timeout method, and returning an error code indicating that the initilazation was unsuccessful.

static usbd_device *stm32f107_usbd_init(void)
{
OTG_FS_GINTSTS = OTG_GINTSTS_MMIS;

OTG_FS_GUSBCFG |= OTG_GUSBCFG_PHYSEL;
/* Enable VBUS sensing in device mode and power down the PHY. */
OTG_FS_GCCFG |= OTG_GCCFG_VBUSBSEN | OTG_GCCFG_PWRDWN;

/* Wait for AHB idle. */
while (!(OTG_FS_GRSTCTL & OTG_GRSTCTL_AHBIDL));
/* Do core soft reset. */
OTG_FS_GRSTCTL |= OTG_GRSTCTL_CSRST;
while (OTG_FS_GRSTCTL & OTG_GRSTCTL_CSRST);

Communicating arm-none-eabi-gcc location on windows

make in top level directory fails with this error:

make[2]: arm-none-eabi-gcc: Command not found

arm-none-eabi-gcc.exe in my system is located at:

C:\Program Files (x86)\GNU Tools ARM Embedded\4.9 2015q1\bin

I've tried running this command:

export PATH="/c//Python27:/c//Program Files (x86)/GNU Tools ARM Embedded/4.9 2015q1/bin:/usr/local/bin:/usr/bin:/bin"

But it doesn't help. What am I doing wrong?

IRQ problems with libopencm3-examples and Luftboot on Lisa/M v2

BACKGROUND:
I have a Lisa/M v2 board with the Aspirin v2.2 10DoM imu on it.
I use mac osx 10.8.4, and installed the newest version of paparazzi tools with macports, the gnu chain I have is:

gcc version 4.7.3 20121207 (release) [ARM/embedded-4_7-branch revision 194305](GNU Tools for ARM Embedded Processors)

I use a BMP to upload my code.

NOW TO THE ISSUE:

When I compile examples/stm/f1/lisa-m-2/usart_printf and upload it everything works as it should (I can see the text output on the usart).

When I compiled examples/stm/f1/lisa-m-2/usart_irq_printf and upload it nothing happens, no usart output at least. By adding led signals into the code I can see that the execution stops behaving as it should right after systick_counter_enable(); is called and I believe when the first interrupt occurs.

I tried this issue on two Lisa/M v2 boards, one factory-flashed, one flashed by myself with Luftboot about a month ago.

I also tried on a Ubuntu machine with the newest version of paparazzi and the gcc toolchain that came with it, same result.

build the miniblink Error for stm32f4-discovery

I'm the new learner for libopencm3, I use ubuntu14.04 environment.
I found that's really strange that I cannot build the example "miniblink"
my step are here, then there is error message,
but the same step and build tick_blink, it will success,
I don't know why

git clone https://github.com/libopencm3/libopencm3-examples.git
cd ./libopencm3-examples
git submodule init
git submodule update
cd libopencm3/
make
cd ../examples/stm32/f4/stm32f4-discovery/miniblink/
make

the error message like this

arm-none-eabi/bin/ld:generated.STM32F407VG.ld:16: warning: memory region `rom' not declared
arm-none-eabi/6.3.1/../../../../arm-none-eabi/bin/ld: invalid origin for memory region ram
collect2: error: ld returned 1 exit status
make: *** [miniblink.elf] Error 1

and generated.STM32F407VG.ld is

EXTERN(vector_table)
ENTRY(reset_handler)
MEMORY
{
 ram (rwx) : ORIGIN = _RAM_OFF, LENGTH = _RAM
}
SECTIONS
{
 .text : {
  *(.vectors)
  *(.text*)
  . = ALIGN(4);
  *(.rodata*)
  . = ALIGN(4);
 } >rom
 .preinit_array : {
  . = ALIGN(4);
  __preinit_array_start = .;
  KEEP (*(.preinit_array))
  __preinit_array_end = .;
 } >rom
 .init_array : {
  . = ALIGN(4);
  __init_array_start = .;
  KEEP (*(SORT(.init_array.*)))
  KEEP (*(.init_array))
  __init_array_end = .;
 } >rom
 .fini_array : {
  . = ALIGN(4);
  __fini_array_start = .;
  KEEP (*(.fini_array))
  KEEP (*(SORT(.fini_array.*)))
  __fini_array_end = .;
 } >rom
 .ARM.extab : {
  *(.ARM.extab*)
 } >rom
 .ARM.exidx : {
  __exidx_start = .;
  *(.ARM.exidx*)
  __exidx_end = .;
 } >rom
 . = ALIGN(4);
 _etext = .;
 .data : {
  _data = .;
  *(.data*)
  . = ALIGN(4);
  _edata = .;
 } >ram AT >rom
 _data_loadaddr = LOADADDR(.data);
 .bss : {
  *(.bss*)
  *(COMMON)
  . = ALIGN(4);
  _ebss = .;
 } >ram
 /DISCARD/ : { *(.eh_frame) }
 . = ALIGN(4);
 end = .;
}
PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));

then if I change a part of linker script, it will work successfully,

MEMORY
{
	rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
	ram (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
}

makefile.include still has lots of duplication

There's virtually identical copies of makefile.include for many families.

The only real differences are:

  • the name of the library
  • ARCH_FLAGS (for hard/soft float etc)
  • the -DSTM32_XX (and similar)

We should maybe just have a makefile.rules and then even simpler per platform makefiles?

Downsides are that it's a little harder to just copy it into your own project?

Don't build .bin, .hex, .srec, .list, .map unless requested

It's a whole heap of files that are generated out of the same elf that should probably just be generated on demand?

There's a quite noticeable timing difference, this is on my quad core laptop with make -j8.

Possibly tweak the rules so that "make [format]" or something will do the right thing if people want it, and update the README appropriately?

karlp@pojak:~/src/libopencm3-examples (elvish *)$ cat timing.elfonly 
real    0m9.513s
user    0m22.125s
sys 0m3.160s

real    0m9.293s
user    0m22.086s
sys 0m3.104s

real    0m9.556s
user    0m22.036s
sys 0m3.190s

karlp@pojak:~/src/libopencm3-examples (elvish *)$ cat timing.allbins 
real    0m12.788s
user    0m33.013s
sys 0m5.438s

real    0m13.022s
user    0m33.410s
sys 0m5.379s

real    0m12.841s
user    0m33.099s
sys 0m5.488s

stm32f3-discovery I2C example not working

Hi,

I've compiled and flashed the i2c example provided on examples/stm32/f3/stm32f3-discovery/i2c but "Hello, we're running" is printed on serial once the micro is reseted and nothing happens.

I've debugged the problem and found out that it gets stuck inside a loop in the i2c_transfer7 function:
libopencm3/lib/stm32/common/i2c_common_v2.c lines 404 - 411:

	bool wait = true;
	while (wait) {
		if (i2c_transmit_int_status(i2c)) {
			wait = false;
		}
		while (i2c_nack(i2c)); /* FIXME Some error */
	}
	i2c_send_data(i2c, *w++);

The i2c_transmit_int_status(i2c) returns always 0, so the while(wait) { loop never exits. The while (i2c_nack(i2c)); line never gets stuck, so it isn't the culprit.

I've compiled with arm-none-eabi-gcc 7.3.0 on Archlinux.

patch to fix C++ linking problem

Yesterday I ran into a few problems linking C++ code with libopencm3 and the provided makefiles. One reason was that it used gcc instead of g++ for linking, the other reason was the missing option --specs=nosys.specs as described in libopencm3/libopencm3#741 .

The following patch fixes these problems for me, but a new variable "OPENCM3_LINK_CPLUSPLUS = 1" has to be set in the makefile to enable C++ linking.

Index: examples/rules.mk
===================================================================
--- examples/rules.mk   (revision 250)
+++ examples/rules.mk   (working copy)
@@ -32,7 +32,11 @@
 
 CC             := $(PREFIX)-gcc
 CXX            := $(PREFIX)-g++
+ifeq ($(OPENCM3_LINK_CPLUSPLUS),1)
+LD             := $(PREFIX)-g++
+else
 LD             := $(PREFIX)-gcc
+endif
 AR             := $(PREFIX)-ar
 AS             := $(PREFIX)-as
 OBJCOPY                := $(PREFIX)-objcopy
@@ -123,7 +127,11 @@
 ###############################################################################
 # Linker flags
 
+ifeq ($(OPENCM3_LINK_CPLUSPLUS),1)
+TGT_LDFLAGS            += --static -nostartfiles --specs=nosys.specs
+else
 TGT_LDFLAGS            += --static -nostartfiles
+endif
 TGT_LDFLAGS            += -T$(LDSCRIPT)
 TGT_LDFLAGS            += $(ARCH_FLAGS) $(DEBUG)
 TGT_LDFLAGS            += -Wl,-Map=$(*).map -Wl,--cref
@@ -208,6 +216,10 @@
        @#printf "  CXX     $(*).cpp\n"
        $(Q)$(CXX) $(TGT_CXXFLAGS) $(CXXFLAGS) $(TGT_CPPFLAGS) $(CPPFLAGS) -o $(*).o -c $(*).cpp
 
+%.o: %.C
+       @#printf "  CXX     $(*).C\n"
+       $(Q)$(CXX) $(TGT_CXXFLAGS) $(CXXFLAGS) $(TGT_CPPFLAGS) $(CPPFLAGS) -o $(*).o -c $(*).C
+
 clean:
        @#printf "  CLEAN\n"
        $(Q)$(RM) *.o *.d *.elf *.bin *.hex *.srec *.list *.map generated.* ${OBJS} ${OBJS:%.o:%.d}

Ooh, it also recognizes *.C files as C++ files :)

(edited: i've put the patch into a code block)

Warning while building cdcacm.c

While building the examples, the following new warning is created with the newest libopencm3 master:

libopencm3-examples/examples/stm32/f1/stm32-h103/usb_cdcacm$ make
cdcacm.c: In function 'cdcacm_set_config':
cdcacm.c:232:5: warning: passing argument 4 of 'usbd_register_control_callback' from incompatible pointer type
     cdcacm_control_request);
     ^
In file included from cdcacm.c:23:0:
../../../../../libopencm3//include/libopencm3/usb/usbd.h:130:12: note: expected 'usbd_control_callback' but argument is of type 'enum usbd_request_return_codes (*)(struct usbd_device *, struct usb_setup_data *, uint8_t **, uint16_t *, void (**)(struct usbd_device *, struct usb_setup_data *))'
 extern int usbd_register_control_callback(usbd_device *usbd_dev, uint8_t type,
            ^

usb_cdcacm wont compile on stm23f4-discovery

Trying to compile in Platformio, and got this:
src/usbcdc.cpp:146:3: error: elements of array 'const usb_interface ifaces []' have incomplete type } };
^
src/usbcdc.cpp:146:3: error: storage size of 'ifaces' isn't known src/usbcdc.cpp: In function 'void cdcacm_set_config(usbd_device*, uint16_t)':

src/usbcdc.cpp:222:27: error: invalid conversion from 'int (*)(usbd_device*, usb_setup_data*, uint8_t**, uint16_t*, void (**)(usbd _device*, usb_setup_data*)) {aka int (*)(_usbd_device*, usb_setup_data*, unsigned char**, short unsigned int*, void (**)(_usbd_dev ice*, usb_setup_data*))}' to 'usbd_control_callback {aka int (*)(_usbd_device*, usb_setup_data*, unsigned char**, short unsigned i nt*, int (**)(_usbd_device*, usb_setup_data*))}' [-fpermissive] cdcacm_control_request);
^
In file included from src/usbcdc.cpp:23:0: /home/vlad/.platformio/packages/framework-libopencm3/include/libopencm3/usb/usbd.h:94:12: error: initializing argument 4 of 'int usbd_register_control_callback(usbd_device*, uint8_t, uint8_t, usbd_control_callback)' [-fpermissive] extern int usbd_register_control_callback(usbd_device *usbd_dev, uint8_t type, ^ Compiling .pioenvs/disco_f407vg/FrameworkLibOpenCM3/lib/stm32/common/adc_common_v1.o

Any help?

Makefile appends - to $(PREFIX)

The status quo is to use, for example, $(PREFIX)gcc instead of $(PREFIX)-gcc. (i.e. PREFIX=arm-none-eabi- instead of PREFIX=arm-none-eabi)

This makes it incompatible with projects that use the former, as libopencm3 will use arm-none-eabi--gcc instead.

bad examples

https://github.com/libopencm3/libopencm3-examples/blob/master/examples/stm32/f1/stm32-h103/exti_rising_falling/exti_rising_falling.c

does not mention the AFIO requirements if you happen to want to change to another port for the EXTI

That's wrong, exti_select_source() sets the SYSCFG or the AFIO registers depending on target. original reported bug was misidagnosed.

examples/stm32/f1/other/usb_hid/usbhid.c and lots of others copied there use HSI for USB on F1, which is really not supported, even though it sometimes works. Should replace them all with hse8_72, and usb div 1.5 to show the "right" way of doing it

Having examples with less restrictive license than LGPL

Would it make any sense to license examples as something less restrictive than LGPL? (such as BSD or even public domain)

Libopencm3 is really nice to use,and it might enjoy more widespread adaptation if users would be able to do base their creations on the examples without have to worry about LGPL's restrictions.

As long as we are cleaning Makefiles ... fpu support

The standard Makefile.include for the STM32F4 includes hard floats (yay!) but when you are using the ARM toolchain (launchpad.net version) and you try to link with -lm it gets the non-FPU version. To get the FPU version you have to add

-L$(TOOLCHAINDIR)/lib/fpu -L$(TOOLCHAINDIR)/lib so that lib/fpu is searched first. At that point it works fine. Also I found that working with my own additional library (which has the utility routines I wrote in it) if I add 'LDFLAGS += -lmylib to the Makefile where the binary is built the default Makefile.include puts libopencm3_stm32.a ahead of it in LDFLAGS and linking fails. But changing the build rule for .elf to put the -llibopencm3_stm32.a on the build rule instead $(LDFLAGS) comes first, allows it to build correctly.

Alignment for USB structs

Various USB examples contain structs like usb_device_descriptor which are passed to usb_copy_to_pm, which will read them 16 bit at a time. If the struct happens not to be aligned, this causes a performance penalty on Cortex-M3 upwards, and even breaks on Cortex-M0 which doesn't support unaligned access at all (I ran into this while porting an USB example to STM32L0). gcc supports __attribute__ ((aligned (2))) for variables, which could be used to ensure proper alignment. I don't know if using this feature is worth it for the existing examples, but we definitely have to keep this in mind when USB examples are ported to controllers with an M0 core.

`make` invoked inside the example directory does not work

When invoking make from the example directory build does not proceed and gives following error:
make: *** No rule to make target 'target.elf', needed by 'elf'. Stop.

  • Clone the examples and initialize libopencm3 submodule
  • cd examples/stm32/f1/stm32-h103/timer
  • OPENCM3_DIR=../../../../../libopencm3/ make

stlink-flash target not supported?

I was looking at reusing the makefiles from the examples here and noticed the stlink-flash target doesn't seem to be fully setup. In Makefile.rules there's a definition for the %.stlink-flash target that runs st-flash here: https://github.com/libopencm3/libopencm3-examples/blob/master/examples/Makefile.rules#L197-L199 However I don't see anything in the file that depends on a $(BINARY).stlink-flash target which would trigger that flashing rule.

I think there should be something like stlink-flash: $(BINARY).stlink-flash added to this block that generates these flashing targets: https://github.com/libopencm3/libopencm3-examples/blob/master/examples/Makefile.rules#L134-L135 That way you could run 'make stlink-flash' in an example folder and it would use st-flash to upload the binary. Just wanted to check am I missing something else that adds that rule, or would this be a useful pull to send back to this repo?

Thanks for providing the great library & examples BTW!

spi_init_master should be more generic.

I manged to issue a "pull request" for the libopencm3.
But somehow my git is now messed up, so I'm getting push/pull/merge errors when I try to clean up the patch. So... here is the patch:

diff --git a/examples/stm32/f1/lisa-m-1/usb_hid/usbhid.c b/examples/stm32/f1/lisa-m-1/usb_hid/usbhid.c
index dd84f80..17765c5 100644
--- a/examples/stm32/f1/lisa-m-1/usb_hid/usbhid.c
+++ b/examples/stm32/f1/lisa-m-1/usb_hid/usbhid.c
@@ -345,11 +345,11 @@ int main(void)
        /* Force to SPI mode. This should be default after reset! */
        SPI2_I2SCFGR = 0;
        spi_init_master(SPI2,
-                       SPI_CR1_BAUDRATE_FPCLK_DIV_256,
-                       SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE,
-                       SPI_CR1_CPHA_CLK_TRANSITION_2,
-                       SPI_CR1_DFF_8BIT,
-                       SPI_CR1_MSBFIRST);
+                       SPI_BAUDRATE_CLK_DIV_256,
+                       SPI_CLK_TO_1_WHEN_IDLE,
+                       SPI_LATCH_RISING,
+                       SPI_FORMAT_8BIT,
+                       SPI_MSBFIRST);
        /* Ignore the stupid NSS pin. */
        spi_enable_software_slave_management(SPI2);
        spi_set_nss_high(SPI2);
diff --git a/examples/stm32/f1/lisa-m-2/spi/spi.c b/examples/stm32/f1/lisa-m-2/spi/spi.c
index f94aaeb..b1f0c0a 100644
--- a/examples/stm32/f1/lisa-m-2/spi/spi.c
+++ b/examples/stm32/f1/lisa-m-2/spi/spi.c
@@ -68,8 +68,8 @@ static void spi_setup(void) {
    * Data frame format: 8-bit
    * Frame format: MSB First
    */
-  spi_init_master(SPI1, SPI_CR1_BAUDRATE_FPCLK_DIV_64, SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE,
-                  SPI_CR1_CPHA_CLK_TRANSITION_2, SPI_CR1_DFF_8BIT, SPI_CR1_MSBFIRST);
+  spi_init_master(SPI1, SPI_BAUDRATE_CLK_DIV_64, SPI_CLK_TO_1_WHEN_IDLE,
+                  SPI_LATCH_RISING, SPI_FORMAT_8BIT, SPI_MSBFIRST);

   /*
    * Set NSS management to software.
diff --git a/examples/stm32/f1/lisa-m-2/spi_dma/spi_dma.c b/examples/stm32/f1/lisa-m-2/spi_dma/spi_dma.c
index bf948ba..b460244 100644
--- a/examples/stm32/f1/lisa-m-2/spi_dma/spi_dma.c
+++ b/examples/stm32/f1/lisa-m-2/spi_dma/spi_dma.c
@@ -97,12 +97,12 @@ static void spi_setup(void) {
         * Frame format: MSB First
         */
 #if USE_16BIT_TRANSFERS
-       spi_init_master(SPI1, SPI_CR1_BAUDRATE_FPCLK_DIV_64, SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE,
-                       SPI_CR1_CPHA_CLK_TRANSITION_2, SPI_CR1_DFF_16BIT, SPI_CR1_MSBFIRST);
+#define MY_FORMAT SPI_FORMAT_16BIT
 #else
-       spi_init_master(SPI1, SPI_CR1_BAUDRATE_FPCLK_DIV_64, SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE,
-                       SPI_CR1_CPHA_CLK_TRANSITION_2, SPI_CR1_DFF_8BIT, SPI_CR1_MSBFIRST);
+#define MY_FORMAT SPI_FORMAT_8BIT
 #endif
+       spi_init_master(SPI1, SPI_BAUDRATE_CLK_DIV_64, SPI_CLK_TO_1_WHEN_IDLE,
+                       SPI_LATCH_RISING, MY_FORMAT, SPI_MSBFIRST);

        /*
         * Set NSS management to software.
diff --git a/examples/stm32/f1/lisa-m-2/spi_dma_adv/spi_dma_adv.c b/examples/stm32/f1/lisa-m-2/spi_dma_adv/spi_dma_adv.c
index 2182865..5947fb6 100644
--- a/examples/stm32/f1/lisa-m-2/spi_dma_adv/spi_dma_adv.c
+++ b/examples/stm32/f1/lisa-m-2/spi_dma_adv/spi_dma_adv.c
@@ -107,13 +107,14 @@ static void spi_setup(void) {
         * Frame format: MSB First
         */
 #if USE_16BIT_TRANSFERS
-       spi_init_master(SPI1, SPI_CR1_BAUDRATE_FPCLK_DIV_64, SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE,
-                       SPI_CR1_CPHA_CLK_TRANSITION_2, SPI_CR1_DFF_16BIT, SPI_CR1_MSBFIRST);
-#else
-       spi_init_master(SPI1, SPI_CR1_BAUDRATE_FPCLK_DIV_64, SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE,
-                       SPI_CR1_CPHA_CLK_TRANSITION_2, SPI_CR1_DFF_8BIT, SPI_CR1_MSBFIRST);
+#define MY_BIT_FORMAT SPI_FORMAT_16BIT
+#else 
+#define MY_BIT_FORMAT SPI_FORMAT_8BIT
 #endif

+       spi_init_master(SPI1, SPI_BAUDRATE_CLK_DIV_64, SPI_CLK_TO_1_WHEN_IDLE,
+                       SPI_LATCH_RISING, MY_BIT_FORMAT, SPI_MSBFIRST);
+
        /*
         * Set NSS management to software.
         *
diff --git a/examples/stm32/f2/jobygps/spi_test/spi_test.c b/examples/stm32/f2/jobygps/spi_test/spi_test.c
index bb570c2..10d6f65 100644
--- a/examples/stm32/f2/jobygps/spi_test/spi_test.c
+++ b/examples/stm32/f2/jobygps/spi_test/spi_test.c
@@ -45,8 +45,8 @@ static void spi_setup(void)
        gpio_set_af(GPIOB, GPIO_AF5, GPIO13 | GPIO14 | GPIO15);

        /* Setup SPI parameters. */
-       spi_init_master(SPI2, SPI_CR1_BAUDRATE_FPCLK_DIV_256, SPI_CR1_CPOL,
-                       SPI_CR1_CPHA, SPI_CR1_DFF_8BIT, SPI_CR1_MSBFIRST);
+       spi_init_master(SPI2, SPI_BAUDRATE_CLK_DIV_256, SPI_CLK_TO_1_WHEN_IDLE,
+                       SPI_LATCH_RISING, SPI_FORMAT_8BIT, SPI_MSBFIRST);
        spi_enable_ss_output(SPI2); /* Required, see NSS, 25.3.1 section. */

        /* Finally enable the SPI. */

error: unknown type name 'cookie_io_functions_t' when trying to compile with GCC 5.3.x

I'm trying to compile libopencm3-examples on Arch Linux (LC_ALL=C make V=1), and I get the following error: when the make process reaches examples/stm32/f0/stm32f0-discovery/usart_stdio:

make[1]: Entering directory '/home/chris/src/stm32/libopencm3-examples/examples/stm32/f0/stm32f0-discovery/usart_stdio'
Using /home/chris/src/stm32/libopencm3-examples/libopencm3 path to library
arm-none-eabi-gcc -Os -g -Wextra -Wshadow -Wimplicit-function-declaration -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes -fno-common -ffunction-sections -fdata-sections -MD -Wall -Wundef -I/home/chris/src/stm32/libopencm3-examples/libopencm3/include -DSTM32F0 -mthumb -mcpu=cortex-m0 -msoft-float -o usart_stdio.o -c usart_stdio.c
usart_stdio.c: In function 'usart_setup':
usart_stdio.c:67:2: error: unknown type name 'cookie_io_functions_t'
  cookie_io_functions_t stub = { _iord, _iowr, NULL, NULL };
  ^

The same unknown type error occurs when trying to compile examples/stm32/f4/stm32f429i-discovery/lcd-dma.

I'm using arm-none-eabi-gcc version 5.3.0 from this package but the same error occurs with version 5.3.1 20160307 from the toolchain launchpad distribution.

I also have the arm-non-eabi-newlib package installed, which places its files under /usr/arm-non-eabi, but he launchpad toolchain comes with its own copy of newlib too, AFAICS.

What am I missing?

New Committers?

We need an additional committer or two on this repo.

So Piotr is busy elsewhere it seems and this repo is getting more and more commits backed up waiting to be integrated. I've created the equivalents for the STM32F429-Discovery (the "Disco" board) and am going to port my LCD example to it. It would be nice to put it here.

reuse steps "don't work"

To be confirmed, but clearly needs rewording at least..

19:40 < Roklobsta> the instructions on https://github.com/libopencm3/libopencm3-examples README 
                   don't work.  "make: *** No rule to make target `miniblink.elf', needed by 
                   `elf'.  Stop."
19:54 < Roklobsta> ah i did mean only the part from REUSE onwards.
19:54 < Roklobsta> the parts before were fine.
19:54 < Roklobsta> sorry should have been clearer.

General Full Example Compile Error

Hi,

I've just run a make on the entire lot of examples and came across the following. The first 2 don't bother me, it's the last 2...

I'll look into it in the mean time, but if someone else could too as I rarely have free time..

CC sync.c
../../cm3/sync.c:30:2: warning: #warning "sync not supported on ARMv6-M arch" [-Wcpp]
#warning "sync not supported on ARMv6-M arch"

CC sync.c
../../cm3/sync.c:30:2: warning: #warning "sync not supported on ARMv6-M arch" [-Wcpp]
#warning "sync not supported on ARMv6-M arch"

BUILD examples/stm32/f4/stm32f4-discovery/usb_cdcacm/
cdcacm.c: In function 'main':
cdcacm.c:242:4: warning: passing argument 4 of 'usbd_init' discards 'const' qualifier from pointer target type [enabled by default]
usbd_control_buffer, sizeof(usbd_control_buffer));
^
In file included from cdcacm.c:23:0:
/Users/adriansluijters/Documents/Developer/STM32/libopencm3-examples/libopencm3/include/libopencm3/usb/usbd.h:62:22: note: expected 'const char *' but argument is of type 'const char * const'
extern usbd_device * usbd_init(const usbd_driver *driver,
^

Cheers

A

Multithreading example

I would love to see some examples for multithreading. Are there any? Is it possible to achieve this functionality without full-blown RTOS just with pure libopencm3?

f3 disco usb cdc acm example looks dodgy

usb_setup() includes calls that are "setting up usart2 on gpio a11,a12" but those are a) not used, and b) the usb pins, and c) the wrong AF

I suspect those lines can just be dropped, but I don't have an f3 board to try that out.

Question: prescaler for timers.

Hello,
My board is based on MCU stm32f103c8t6.
I am learning and playing with examples and get some misunderstanding with setting prescaler for timers.
I use TIM4, it is connected to APB1 and has frequency 36Mhz for me.
I want counter to be updated every 1ms.
What prescaler should I use: 36000 or 35999?
I have checked examples and here I see 36000:
https://github.com/libopencm3/libopencm3-examples/blob/master/examples/stm32/f1/stm32-h103/timer/timer.c#L91

But here prescaler is decremented by 1 :
https://github.com/libopencm3/libopencm3-examples/blob/master/examples/stm32/l1/stm32l-discovery/button-irq-printf/main.c#L142

According to reference manual, real prescaler should be decremented:

Bits15:0 PSC[15:0]:Prescalervalue
The counter clock frequency CK_CNT is equal to fCK_PSC / (PSC[15:0] + 1).

Is it error in examples or libopencm3 decrements prescaler before set it to register?

Thank you,
Artem

Some examples use deprecated defines.

Hi,

Both usart and the adc examples on the stm32f0 and the i2c example of the stm32f3 devices are still using deprecated defines (based on libopencm3 head, commit 3922cc7).

usart and adc examples on stm32f0 (stm32f0-discovery).

This examples use the following:

usart_set_stopbits(USART1, USART_CR2_STOP_1_0BIT);

USART_CR2_STOP_1_0BIT it's only used on this examples, all other usart examples use one of the following defines (usart_cr2_stopbits):
#define USART_STOPBITS_1 USART_CR2_STOPBITS_1 /* 1 stop bit /
#define USART_STOPBITS_0_5 USART_CR2_STOPBITS_0_5 /
.5 stop bit /
#define USART_STOPBITS_2 USART_CR2_STOPBITS_2 /
2 stop bits /
#define USART_STOPBITS_1_5 USART_CR2_STOPBITS_1_5 /
1.5 stop bit*/

So the following fix it:
usart_set_stopbits(USART1, USART_STOPBITS_1);

i2c example on stm32f3 (stm32f3-discovery).

I2C_CR1_DNF_DISABLED is used and it was removed in commit cb2eff (October 26, 2017). using 0 is fine in this case.

Error:
i2c_set_digital_filter(I2C1, I2C_CR1_DNF_DISABLED);

Solved with:
i2c_set_digital_filter(I2C1, 0);

Regards,
Carlos

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.