New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project idea: better embedded driver support #4

Open
thejpster opened this Issue Oct 28, 2016 · 33 comments

Comments

Projects
None yet
7 participants
@thejpster
Contributor

thejpster commented Oct 28, 2016

How about working on some embedded dev boards and building up some driver support crates? UARTs, SPI, PWM, that sort of thing. I'm thinking things along the line of japaric's F3, or my Launchpad/LM4F120. Looking at a variety of hardware platforms might help #rust-embedded work towards a common API for common peripherals.

If you get the right boards, they're relatively cheap. I just picked up some Kinetis Cortex-M0+ boards (with 5V I/O!!) for about £10. TI Launchpads are about the same. Raspberry Pi Zeros even. You might get a sponsor to cover the cost, and developers can take the boards away at the end to carry on working.

@japaric has created an Etherpad for elaborating on some of the ideas here. Check it out.

@skade

This comment has been minimized.

Show comment
Hide comment
@skade

skade Oct 28, 2016

Contributor

That sounds like a cool idea and there's still some time for people to buy boards. Would you like to be personally involved? (Maybe even on site in Cambridge or London, maybe. In London, we are still specifically searching for people, we might have a room at Mozilla London) 😉

Contributor

skade commented Oct 28, 2016

That sounds like a cool idea and there's still some time for people to buy boards. Would you like to be personally involved? (Maybe even on site in Cambridge or London, maybe. In London, we are still specifically searching for people, we might have a room at Mozilla London) 😉

@thejpster

This comment has been minimized.

Show comment
Hide comment
@thejpster

thejpster Oct 28, 2016

Contributor

I would like to be involved but I need to check availability for that weekend. Cambridge would be better than London (I started #5 for that).

Contributor

thejpster commented Oct 28, 2016

I would like to be involved but I need to check availability for that weekend. Cambridge would be better than London (I started #5 for that).

@skade skade changed the title from Project idea to Project idea: better embedded driver support Oct 28, 2016

@skade

This comment has been minimized.

Show comment
Hide comment
@skade

skade Oct 28, 2016

Contributor

I edited the title to better express what the idea is. I hope thats a good one, feel free to change if you come up with a better one.

Contributor

skade commented Oct 28, 2016

I edited the title to better express what the idea is. I hope thats a good one, feel free to change if you come up with a better one.

@japaric

This comment has been minimized.

Show comment
Hide comment
@japaric

japaric Oct 28, 2016

Thanks to Rust Belt Rust (shameless plug) we got around 15 rustaceans with the right hardware (STM32F3DISCOVERY boards). I've informed all of them about this. I don't know how many of them are in Europe or can be in Europe for the date of novemb.rs but perhaps some of them can join remotely.

I'm not in Europe but would love to participate remotely during the hours that are not crazy for me (I'm on UTC -5)

japaric commented Oct 28, 2016

Thanks to Rust Belt Rust (shameless plug) we got around 15 rustaceans with the right hardware (STM32F3DISCOVERY boards). I've informed all of them about this. I don't know how many of them are in Europe or can be in Europe for the date of novemb.rs but perhaps some of them can join remotely.

I'm not in Europe but would love to participate remotely during the hours that are not crazy for me (I'm on UTC -5)

@skade

This comment has been minimized.

Show comment
Hide comment
@skade

skade Oct 28, 2016

Contributor

@japaric they are readily available at German resellers. I'm pretty sure DHL can make us tremble in fear, though. The problem is more of a budget one, if we want to supply people with them.

Contributor

skade commented Oct 28, 2016

@japaric they are readily available at German resellers. I'm pretty sure DHL can make us tremble in fear, though. The problem is more of a budget one, if we want to supply people with them.

@thejpster

This comment has been minimized.

Show comment
Hide comment
@thejpster

thejpster Oct 28, 2016

Contributor

I'd like to make sure we get a spread of different hardware available too. By implementing several UART drivers for several boards, we can hopefully work out what a generic UART trait might look like. There are many boards using Cortex-M4 based microcontrollers available at the £10-£15 price point.

Contributor

thejpster commented Oct 28, 2016

I'd like to make sure we get a spread of different hardware available too. By implementing several UART drivers for several boards, we can hopefully work out what a generic UART trait might look like. There are many boards using Cortex-M4 based microcontrollers available at the £10-£15 price point.

@SimonSapin

This comment has been minimized.

Show comment
Hide comment
@SimonSapin

SimonSapin Oct 29, 2016

Where C or C++ drivers exist, https://github.com/servo/rust-bindgen could be used to generate Rust bindings for them. I've had success doing this for Teensy hardware: https://github.com/jamesmunns/teensy3-rs

One downside is that FFI functions require unsafe to call, and constants generated from #define may require casting with as.

Where C or C++ drivers exist, https://github.com/servo/rust-bindgen could be used to generate Rust bindings for them. I've had success doing this for Teensy hardware: https://github.com/jamesmunns/teensy3-rs

One downside is that FFI functions require unsafe to call, and constants generated from #define may require casting with as.

@japaric

This comment has been minimized.

Show comment
Hide comment
@japaric

japaric Oct 29, 2016

@SimonSapin I just took a look at the teensy3 crate and it seems it only exposes a blocking API. Do you know if the underlying C/C++ libraries expose an async/non-blocking API or if/how the Teensy API can be used to run concurrent tasks?

The other issue I see there is that the documentation says that e.g. Serial is supposed to be a singleton but it exposes it a struct that the user can create many instances of. This is probably not a problem for the teensy3 crate right now because it doesn't (seem to) expose async IO, interrupts or threads/tasks but once you introduce any of those then you'll realize that you want to enforce peripheral "ownership" in your API or at very least expose peripherals as Mutexed globals.

Those are the three topics I'd like to discuss during this event: async IO, "ownership" of hardware and dealing with interrupts. FWIW, I've begun to experiment with futures-based async IO in my f3 crate in this branch.

I don't have experience with production embedded systems so I don't know how C applications dealt with those (callbacks?) but I hope that someone (@thejpster?) who has the experience shows up at the event because it would be illuminating.

japaric commented Oct 29, 2016

@SimonSapin I just took a look at the teensy3 crate and it seems it only exposes a blocking API. Do you know if the underlying C/C++ libraries expose an async/non-blocking API or if/how the Teensy API can be used to run concurrent tasks?

The other issue I see there is that the documentation says that e.g. Serial is supposed to be a singleton but it exposes it a struct that the user can create many instances of. This is probably not a problem for the teensy3 crate right now because it doesn't (seem to) expose async IO, interrupts or threads/tasks but once you introduce any of those then you'll realize that you want to enforce peripheral "ownership" in your API or at very least expose peripherals as Mutexed globals.

Those are the three topics I'd like to discuss during this event: async IO, "ownership" of hardware and dealing with interrupts. FWIW, I've begun to experiment with futures-based async IO in my f3 crate in this branch.

I don't have experience with production embedded systems so I don't know how C applications dealt with those (callbacks?) but I hope that someone (@thejpster?) who has the experience shows up at the event because it would be illuminating.

@thejpster

This comment has been minimized.

Show comment
Hide comment
@thejpster

thejpster Oct 30, 2016

Contributor
Contributor

thejpster commented Oct 30, 2016

@SimonSapin

This comment has been minimized.

Show comment
Hide comment
@SimonSapin

SimonSapin Oct 30, 2016

@japaric For Serial specifically, the underlying library is documented at https://www.pjrc.com/teensy/td_serial.html. It looks like the Serial.available() and Serial.read() pair can do non-blocking reads, but I don’t know about writing. As to concurrency with that API (which is largely that of Arduino) I don’t know if anyone ever tried.

The Rust Serial struct has no field / is zero-sized. It’s effectively a singleton, that struct only exists because I think the foo.bar() method call syntax looks better than Foo::bar().

What is the point of enforcing device ownership or using Mutex when the hardware does not provide paralellism or preemption?

Anyway, my approach to this project was to get something running quickly for a very simple application, all over the span of a few weekends. So any design choice is more likely the first thing that worked rather than a rejection of alternatives. If it turns out there are good reasons to change it nothing in teensy3-rs is frozen, as long as someone wants to spend the time/effort to develop it.

@japaric For Serial specifically, the underlying library is documented at https://www.pjrc.com/teensy/td_serial.html. It looks like the Serial.available() and Serial.read() pair can do non-blocking reads, but I don’t know about writing. As to concurrency with that API (which is largely that of Arduino) I don’t know if anyone ever tried.

The Rust Serial struct has no field / is zero-sized. It’s effectively a singleton, that struct only exists because I think the foo.bar() method call syntax looks better than Foo::bar().

What is the point of enforcing device ownership or using Mutex when the hardware does not provide paralellism or preemption?

Anyway, my approach to this project was to get something running quickly for a very simple application, all over the span of a few weekends. So any design choice is more likely the first thing that worked rather than a rejection of alternatives. If it turns out there are good reasons to change it nothing in teensy3-rs is frozen, as long as someone wants to spend the time/effort to develop it.

@japaric

This comment has been minimized.

Show comment
Hide comment
@japaric

japaric Oct 30, 2016

@thejpster Very enlightening! Thank you. I've got a few questions but I'm going to ask them over IRC to avoid going (too) off-topic.


@SimonSapin

when the hardware does not provide paralellism or preemption?

Oh, but it does! Interrupts are a preemption mechanism and their "handlers" (the functions that get called when an interrupt occurs) have their own "execution context" (stack frame) so in a sense they are like threads. As soon as your program has to dealt with interrupts, you run into the need of wanting to exchange between your main thread / loop and interrupts and the "obvious" way is to use a static muts which are a can of worms data races.

The issue I was referring to about Serial looks like this:

fn main() -> ! {
    // .. initialization stuff ..

    loop {
        // NOTE blocking!
        Serial.write_all(b"The quick brown fox jumps over the lazy dog.");
    }
}

// This is an interrupt handler. It runs e.g. every 10 milliseconds
// When those 10 milliseconds pass the processor will *stop* executing the `main` function,
// it will then execute this function and then return to `main` when this function is done
fn tim7() {
    // NOTE blocking as well
    Serial.putc(b'X');
}

This without an OS just using hardware features. At best this will print something like this:

ThXe XquXic...

At worst the interrupt handler may kick while write_all was mid through modifying several registers and the interrupt handler will start its execution with registers in a bad/unexpected state.

"But nobody writes code like that" is not a good argument. The question here is whether the compiler can stop you from writing racy code like the above. And I think it can, if you structure your code differently:

fn main() -> ! {
    // .. initialization stuff ..

    // A single instance of Serial
    let mut serial = Serial::init_once();

    loop {
        if done_with_previous_write {
            // NOTE Non-blocking!
            serial.async_write_all(b"The quick brown fox jumps over the lazy dog.");
        }

        // moved the interrupt handler logic into the main loop
        if ten_milliseconds_have_passed {
            serial.putc(b'X');
        }
    }
}

This should error with "trying to mutably borrow serial twice". But if you want to write code like that, code that runs concurrent tasks in the main loop, you can't use a blocking API.

Anyway, my approach to this project was to get something running quickly for a very simple application ...

Totally understandable. I hope we can continue working on top of the teensy3 crate during this event.


OK, back to the main topic. It seems to me that if we want to work on designing a non-blocking API we should have some list of applications that have to deal with concurrent tasks / events that we must implement during this event. And implementing those applications will trigger discussion and tease out the API design.

The applications should be implementable without needing (too much) external hardware to keep the cost low. Ideally we should use try to use all the stuff that the development board already have on them.

Possible applications could be:

  • My running example of running two concurrent tasks: a LED that blinks, say, every 100 ms and an "echo server" running on top of the serial interface. (echo server means that the microcontroller must send back every byte that the user sends through the serial interface). This requires extra hardware like a Serial <-> USB converter or a Serial <-> Bluetooth module (RFCOMM) to be able to have a person interact with the "server" through a laptop (using minicom, putty or other serial emulator program)
  • Two concurrent tasks: Blinking an LED at, say, 100 ms and turning on/off a different LED when the user presses a button. This one may be tricky because of the debouncing logic. But most boards should have two LEDs and an user button on them.
  • Reading two sensors / analog signals at different rates, say, 30 Hz and 40 Hz and, if available, report them to a user through a serial interface. Needs extra hardware. Perhaps, instead of reporting though serial, the micro could dim two LEDs, using PWM, based on the analog values.

Once we have of these applications we can merge the tasks in them to build more complex applications.

These applications also force you to actually write the peripheral/sensor drivers.

Thoughts about this last idea? Can think of more "applications" to tackle during novemb.rs?

japaric commented Oct 30, 2016

@thejpster Very enlightening! Thank you. I've got a few questions but I'm going to ask them over IRC to avoid going (too) off-topic.


@SimonSapin

when the hardware does not provide paralellism or preemption?

Oh, but it does! Interrupts are a preemption mechanism and their "handlers" (the functions that get called when an interrupt occurs) have their own "execution context" (stack frame) so in a sense they are like threads. As soon as your program has to dealt with interrupts, you run into the need of wanting to exchange between your main thread / loop and interrupts and the "obvious" way is to use a static muts which are a can of worms data races.

The issue I was referring to about Serial looks like this:

fn main() -> ! {
    // .. initialization stuff ..

    loop {
        // NOTE blocking!
        Serial.write_all(b"The quick brown fox jumps over the lazy dog.");
    }
}

// This is an interrupt handler. It runs e.g. every 10 milliseconds
// When those 10 milliseconds pass the processor will *stop* executing the `main` function,
// it will then execute this function and then return to `main` when this function is done
fn tim7() {
    // NOTE blocking as well
    Serial.putc(b'X');
}

This without an OS just using hardware features. At best this will print something like this:

ThXe XquXic...

At worst the interrupt handler may kick while write_all was mid through modifying several registers and the interrupt handler will start its execution with registers in a bad/unexpected state.

"But nobody writes code like that" is not a good argument. The question here is whether the compiler can stop you from writing racy code like the above. And I think it can, if you structure your code differently:

fn main() -> ! {
    // .. initialization stuff ..

    // A single instance of Serial
    let mut serial = Serial::init_once();

    loop {
        if done_with_previous_write {
            // NOTE Non-blocking!
            serial.async_write_all(b"The quick brown fox jumps over the lazy dog.");
        }

        // moved the interrupt handler logic into the main loop
        if ten_milliseconds_have_passed {
            serial.putc(b'X');
        }
    }
}

This should error with "trying to mutably borrow serial twice". But if you want to write code like that, code that runs concurrent tasks in the main loop, you can't use a blocking API.

Anyway, my approach to this project was to get something running quickly for a very simple application ...

Totally understandable. I hope we can continue working on top of the teensy3 crate during this event.


OK, back to the main topic. It seems to me that if we want to work on designing a non-blocking API we should have some list of applications that have to deal with concurrent tasks / events that we must implement during this event. And implementing those applications will trigger discussion and tease out the API design.

The applications should be implementable without needing (too much) external hardware to keep the cost low. Ideally we should use try to use all the stuff that the development board already have on them.

Possible applications could be:

  • My running example of running two concurrent tasks: a LED that blinks, say, every 100 ms and an "echo server" running on top of the serial interface. (echo server means that the microcontroller must send back every byte that the user sends through the serial interface). This requires extra hardware like a Serial <-> USB converter or a Serial <-> Bluetooth module (RFCOMM) to be able to have a person interact with the "server" through a laptop (using minicom, putty or other serial emulator program)
  • Two concurrent tasks: Blinking an LED at, say, 100 ms and turning on/off a different LED when the user presses a button. This one may be tricky because of the debouncing logic. But most boards should have two LEDs and an user button on them.
  • Reading two sensors / analog signals at different rates, say, 30 Hz and 40 Hz and, if available, report them to a user through a serial interface. Needs extra hardware. Perhaps, instead of reporting though serial, the micro could dim two LEDs, using PWM, based on the analog values.

Once we have of these applications we can merge the tasks in them to build more complex applications.

These applications also force you to actually write the peripheral/sensor drivers.

Thoughts about this last idea? Can think of more "applications" to tackle during novemb.rs?

@japaric

This comment has been minimized.

Show comment
Hide comment
@japaric

japaric Oct 30, 2016

you often want your system blocked in the wfi instruction (wait for interrupt) to save power, rather than spinning madly. -- @thejpster

To increase the difficulty level, we should strive to make the above applications always sleep when there's nothing to do rather than "busy wait" (spin endlessly).

japaric commented Oct 30, 2016

you often want your system blocked in the wfi instruction (wait for interrupt) to save power, rather than spinning madly. -- @thejpster

To increase the difficulty level, we should strive to make the above applications always sleep when there's nothing to do rather than "busy wait" (spin endlessly).

@japaric

This comment has been minimized.

Show comment
Hide comment
@japaric

japaric Nov 4, 2016

So I have been thinking about what we could work on during the event and turns
out there's lot of stuff that we could do. I've collected my ideas into
a public etherpad so others can add their ideas as well. The "focus areas"
I've proposed are:

  • Onboarding. Getting Rustaceans, both beginners and experienced with embedded
    systems but not with embedded Rust development, up to speed with embedded Rust
    development.
  • API design. APIs (traits!) for things like Serial, I2C, PWM, etc. that are
    general enough to be implementable for different microcontrollers / dev
    boards. We can start with a blocking API and then work on an async API.
  • Tackling open ended problems. How to safely deal with interrupts, what does a
    Rustic preemptive scheduler looks like, when is it unsafe to read / write a
    register, etc.
  • IDE integration. I've configured Eclipse before for embedded C development.
    Perhaps, we can something similar for embedded Rust development.

The etherpad contains way more details about these areas. Let's discuss the
details here.

The etherpad also contains a list of participants which is more like a hardware
/ time zone survey. I encourage you to add yourself to it if you plan to
participate in the code sprint.

japaric commented Nov 4, 2016

So I have been thinking about what we could work on during the event and turns
out there's lot of stuff that we could do. I've collected my ideas into
a public etherpad so others can add their ideas as well. The "focus areas"
I've proposed are:

  • Onboarding. Getting Rustaceans, both beginners and experienced with embedded
    systems but not with embedded Rust development, up to speed with embedded Rust
    development.
  • API design. APIs (traits!) for things like Serial, I2C, PWM, etc. that are
    general enough to be implementable for different microcontrollers / dev
    boards. We can start with a blocking API and then work on an async API.
  • Tackling open ended problems. How to safely deal with interrupts, what does a
    Rustic preemptive scheduler looks like, when is it unsafe to read / write a
    register, etc.
  • IDE integration. I've configured Eclipse before for embedded C development.
    Perhaps, we can something similar for embedded Rust development.

The etherpad contains way more details about these areas. Let's discuss the
details here.

The etherpad also contains a list of participants which is more like a hardware
/ time zone survey. I encourage you to add yourself to it if you plan to
participate in the code sprint.

@skade

This comment has been minimized.

Show comment
Hide comment
@skade

skade Nov 4, 2016

Contributor

In general, would someone be able to give me a list of hardware that would be interesting at a certain location (with a full address to send it to)? Also, would someone give me a contact for someone who would be willing to take care of the hardware after it was used for the workshop?

I would be willing to find a way then to maybe get some kits to you, if I can arrange funds.

Email: flo@andersground.net for personal info.

Contributor

skade commented Nov 4, 2016

In general, would someone be able to give me a list of hardware that would be interesting at a certain location (with a full address to send it to)? Also, would someone give me a contact for someone who would be willing to take care of the hardware after it was used for the workshop?

I would be willing to find a way then to maybe get some kits to you, if I can arrange funds.

Email: flo@andersground.net for personal info.

@thejpster

This comment has been minimized.

Show comment
Hide comment
@thejpster

thejpster Nov 4, 2016

Contributor

There seems to be some support for this, so would it be possible to get this mentioned on the novemb.rs front page?

Contributor

thejpster commented Nov 4, 2016

There seems to be some support for this, so would it be possible to get this mentioned on the novemb.rs front page?

@skade

This comment has been minimized.

Show comment
Hide comment
@skade

skade Nov 4, 2016

Contributor

I'll put it in as a project and link to this issue. Takes me a few hours, though.

Contributor

skade commented Nov 4, 2016

I'll put it in as a project and link to this issue. Takes me a few hours, though.

@japaric

This comment has been minimized.

Show comment
Hide comment
@japaric

japaric Nov 4, 2016

would someone be able to give me a list of hardware that would be interesting

My recommendations:

The STM32F3DISCOVERY board is great for beginners as they can follow the rust-discovery material pretty much on their own and I can answer any question about that material. cf. #20

But, in general, any development board with a Cortex-M microcontroller in it plus a programmer (hardware) that are both supported by the OpenOCD project will work. There's lots of boards that fit this description. Some, like the DISCOVERY boards, even have the programmer "on-board" so you don't need any extra hardware other than a DISCOVERY board.

japaric commented Nov 4, 2016

would someone be able to give me a list of hardware that would be interesting

My recommendations:

The STM32F3DISCOVERY board is great for beginners as they can follow the rust-discovery material pretty much on their own and I can answer any question about that material. cf. #20

But, in general, any development board with a Cortex-M microcontroller in it plus a programmer (hardware) that are both supported by the OpenOCD project will work. There's lots of boards that fit this description. Some, like the DISCOVERY boards, even have the programmer "on-board" so you don't need any extra hardware other than a DISCOVERY board.

@skade

This comment has been minimized.

Show comment
Hide comment
@skade

skade Nov 4, 2016

Contributor

Well, with list, I was more thinking about something I can just bash into a web interface, hit "buy" and have it shipped to the location where people find the equipment interesting :D.

Contributor

skade commented Nov 4, 2016

Well, with list, I was more thinking about something I can just bash into a web interface, hit "buy" and have it shipped to the location where people find the equipment interesting :D.

@japaric

This comment has been minimized.

Show comment
Hide comment
@japaric

japaric Nov 4, 2016

Oh, OK. I don't know many retailers other than Mouser and Digikey but I found these links for the F3 board:

The F3 doesn't seem to be available in Digikey Germany or Digikey UK. :-/

Hmm, the mouser site seems to "latch" to a country after the first visit but you can change the country with the "Change Location" button on the top right.

japaric commented Nov 4, 2016

Oh, OK. I don't know many retailers other than Mouser and Digikey but I found these links for the F3 board:

The F3 doesn't seem to be available in Digikey Germany or Digikey UK. :-/

Hmm, the mouser site seems to "latch" to a country after the first visit but you can change the country with the "Change Location" button on the top right.

@thejpster

This comment has been minimized.

Show comment
Hide comment
@thejpster

thejpster Nov 4, 2016

Contributor

The Tiva-C launchpad (which is almost identical to the Stellaris Launchpad I use) is available from Farnell for about £10. As with the STMicro Discovery board, an OpenOCD compatible USB flash tool and debugger is included.

http://uk.farnell.com/texas-instruments/ek-tm4c123gxl/tm4c123g-launchpad-tiva-c-eval/dp/2314937

I think this is an interesting board because it has a close relative which adds Ethernet. Understanding how to support similar, but slightly different, microcontrollers is a useful exercise. Also, IP stacks written in Rust ftw.

http://uk.farnell.com/texas-instruments/ek-tm4c1294xl/eval-brd-tiva-c-connected-launchpad/dp/2399965

I have one or two of the former (the LM4F120 version anyway) and could probably borrow a couple of the latter from work.

As an aside, the STM32F3Discovery is no longer available according to Farnell - http://uk.farnell.com/stmicroelectronics/stm32f3discovery/evaluation-f3-cortex-m4-discovery/dp/2215108

Contributor

thejpster commented Nov 4, 2016

The Tiva-C launchpad (which is almost identical to the Stellaris Launchpad I use) is available from Farnell for about £10. As with the STMicro Discovery board, an OpenOCD compatible USB flash tool and debugger is included.

http://uk.farnell.com/texas-instruments/ek-tm4c123gxl/tm4c123g-launchpad-tiva-c-eval/dp/2314937

I think this is an interesting board because it has a close relative which adds Ethernet. Understanding how to support similar, but slightly different, microcontrollers is a useful exercise. Also, IP stacks written in Rust ftw.

http://uk.farnell.com/texas-instruments/ek-tm4c1294xl/eval-brd-tiva-c-connected-launchpad/dp/2399965

I have one or two of the former (the LM4F120 version anyway) and could probably borrow a couple of the latter from work.

As an aside, the STM32F3Discovery is no longer available according to Farnell - http://uk.farnell.com/stmicroelectronics/stm32f3discovery/evaluation-f3-cortex-m4-discovery/dp/2215108

@japaric

This comment has been minimized.

Show comment
Hide comment
@japaric

japaric Nov 4, 2016

an OpenOCD compatible USB flash tool and debugger is included.

This is very, very important.

@thejpster Do any of these launchpad boards have an on-board Serial <-> USB converter? Or do you need extra hardware to send serial data to a computer? And if they do, can the Serial <-> USB and the debugger functions be used at the same time?

The ST-LINK, the on-board programmer/debugger that DISCOVERY boards ship with, has a Virtual COM Port function (for Serial over USB communication) but can't be used if the ST-LINK is already acting as a debugger. So you need extra hardware to be able to both debug and send serial data to a PC.

japaric commented Nov 4, 2016

an OpenOCD compatible USB flash tool and debugger is included.

This is very, very important.

@thejpster Do any of these launchpad boards have an on-board Serial <-> USB converter? Or do you need extra hardware to send serial data to a computer? And if they do, can the Serial <-> USB and the debugger functions be used at the same time?

The ST-LINK, the on-board programmer/debugger that DISCOVERY boards ship with, has a Virtual COM Port function (for Serial over USB communication) but can't be used if the ST-LINK is already acting as a debugger. So you need extra hardware to be able to both debug and send serial data to a PC.

@thejpster

This comment has been minimized.

Show comment
Hide comment
@thejpster

thejpster Nov 4, 2016

Contributor

Yes, there's a whole extra LM4F dedicated to OpenOCD and USB Serial. I can use OpenOCD and open /dev/ttyAMA0 at the same time.

Contributor

thejpster commented Nov 4, 2016

Yes, there's a whole extra LM4F dedicated to OpenOCD and USB Serial. I can use OpenOCD and open /dev/ttyAMA0 at the same time.

@japaric

This comment has been minimized.

Show comment
Hide comment
@japaric

japaric Nov 4, 2016

@thejpster Awesome. The DISCOVERY has the hardware wired in the right way but the firmware doesn't support it 😞 . (May I should write my own ST-LINK firmware 😈)

japaric commented Nov 4, 2016

@thejpster Awesome. The DISCOVERY has the hardware wired in the right way but the firmware doesn't support it 😞 . (May I should write my own ST-LINK firmware 😈)

@jcsoo

This comment has been minimized.

Show comment
Hide comment
@jcsoo

jcsoo Nov 4, 2016

Putting in my vote for the STM32F4 Discovery (note F4) which is a more powerful variant in the same family. It is also about $15 and comes with the same integrated ST-LINK debugger. There is a lot of material and code online (mostly C) that works with this particular dev board.

Of note, the F4 has an on-board 10/100 Ethernet MAC which you can connect to an external PHY and Ethernet jack. The STM32F4DIS-BB is about $40 and includes Ethernet and a number of other components. There are also cheaper PHY+RJ45 breakout boards that you can find for ~$10. And yes, I am starting on an IP network stack in Rust.

As I look online right now, it looks like the original STM32F4DISCOVERY has now also been discontinued. However, it looks like the STM32F407G-DISC1 is available with the same specifications.

For programming / debugging, the Black Magic Probe V2 is an interesting open source device that should work with most of these devices. It provides simultaneous debug + serial and doesn't even require OpenOCD - you can connect to it directly from GDB once you plug it in.

jcsoo commented Nov 4, 2016

Putting in my vote for the STM32F4 Discovery (note F4) which is a more powerful variant in the same family. It is also about $15 and comes with the same integrated ST-LINK debugger. There is a lot of material and code online (mostly C) that works with this particular dev board.

Of note, the F4 has an on-board 10/100 Ethernet MAC which you can connect to an external PHY and Ethernet jack. The STM32F4DIS-BB is about $40 and includes Ethernet and a number of other components. There are also cheaper PHY+RJ45 breakout boards that you can find for ~$10. And yes, I am starting on an IP network stack in Rust.

As I look online right now, it looks like the original STM32F4DISCOVERY has now also been discontinued. However, it looks like the STM32F407G-DISC1 is available with the same specifications.

For programming / debugging, the Black Magic Probe V2 is an interesting open source device that should work with most of these devices. It provides simultaneous debug + serial and doesn't even require OpenOCD - you can connect to it directly from GDB once you plug it in.

@japaric

This comment has been minimized.

Show comment
Hide comment
@japaric

japaric Nov 4, 2016

includes Ethernet

Right, everyone has their own agenda. @jcsoo will you be willing to lead a group to work on an ethernet/IP stack? I must admit I have no idea how much effort that requires.

the Black Magic Probe V2 is an interesting open source device ...

FWIW, you can use the ST-LINK in any DISCOVERY board to flash another board and the DISCOVERYs only cost like $15. Also, OpenOCD works fine in the three major OSes so I think you'll be only saving yourself from typing one command every now and then if you don't use it.


We should decide on some "deliverables" for the focus areas. I think that for the API design, one of the deliverables could be a crate with traits for blocking IO and just IO; no place for configuration API in that crate. Another deliverable could be extending that crate with async methods or, if it makes sense, different traits for async IO.

I know that @brandonedens wants to work on a preemptive scheduler so that could be a deliverable, assuming they don't get it done before the event. Otherwise, we could test that scheduler during the event on different hardware to see where it falls short.

And so on.


@thejpster Could you copy the etherpad link into the top comment?

japaric commented Nov 4, 2016

includes Ethernet

Right, everyone has their own agenda. @jcsoo will you be willing to lead a group to work on an ethernet/IP stack? I must admit I have no idea how much effort that requires.

the Black Magic Probe V2 is an interesting open source device ...

FWIW, you can use the ST-LINK in any DISCOVERY board to flash another board and the DISCOVERYs only cost like $15. Also, OpenOCD works fine in the three major OSes so I think you'll be only saving yourself from typing one command every now and then if you don't use it.


We should decide on some "deliverables" for the focus areas. I think that for the API design, one of the deliverables could be a crate with traits for blocking IO and just IO; no place for configuration API in that crate. Another deliverable could be extending that crate with async methods or, if it makes sense, different traits for async IO.

I know that @brandonedens wants to work on a preemptive scheduler so that could be a deliverable, assuming they don't get it done before the event. Otherwise, we could test that scheduler during the event on different hardware to see where it falls short.

And so on.


@thejpster Could you copy the etherpad link into the top comment?

@genbattle

This comment has been minimized.

Show comment
Hide comment
@genbattle

genbattle Nov 5, 2016

To add my 2c to the discussion, it would be nice to see some support for the STM Nucleo boards. All Nucleo boards have ST-Link onboard, so should be compatible with OpenOCD, and come with a range of STM MCUs of varying sizes and capabilities. Most of the Nucleo boards are about $10.

They're a little nicer to use than the base discovery boards since they include Arduino-compatible pinouts (they also include discovery-style headers).

To add my 2c to the discussion, it would be nice to see some support for the STM Nucleo boards. All Nucleo boards have ST-Link onboard, so should be compatible with OpenOCD, and come with a range of STM MCUs of varying sizes and capabilities. Most of the Nucleo boards are about $10.

They're a little nicer to use than the base discovery boards since they include Arduino-compatible pinouts (they also include discovery-style headers).

@japaric

This comment has been minimized.

Show comment
Hide comment
@japaric

japaric Nov 5, 2016

should be compatible with OpenOCD

They are, indeed, supported by OpenOCD (grep for nucleo).

it would be nice to see some support for the STM Nucleo boards.

An unsolved problem is figuring out how to organize crates to reduce the effort required to support a new board. There's some previous discussion about that here

japaric commented Nov 5, 2016

should be compatible with OpenOCD

They are, indeed, supported by OpenOCD (grep for nucleo).

it would be nice to see some support for the STM Nucleo boards.

An unsolved problem is figuring out how to organize crates to reduce the effort required to support a new board. There's some previous discussion about that here

@jamesmunns

This comment has been minimized.

Show comment
Hide comment
@jamesmunns

jamesmunns Nov 6, 2016

Hey, sorry to show up late to the party. @thejpster and @japaric you have both hit some really good points here, but I thought I could weigh in on the trait based API.

Since we have traits and composition here, I think the best thing we can do is define the minimum common behavior, and build out functionality based on that.

Using the Serial example, we may come to agreement that this includes something like:

trait Serial {
  fn read(&self) -> Option<u8>;
  fn write(&self, u8) -> Result<(), ()>;
}

It doesn't cover how this is implemented, but allows us to define a common denominator, which can then be composed into more and more complex (or more and more specific) kinds of interfaces. Sometimes blocking will be right, sometimes FIFO-backed non-blocking will be right, sometimes callbacks will be right.

This could be implemented by many kinds of Serial, such as AsyncSerial, BlockingSerial, CallbackSerial, etc. I think the defining characteristic of embedded development is that there is no single abstraction that works for all cases (based on size, speed, etc). Since we can use trait specialization at compile time, this helps remove ambiguity at "zero cost".

Later, when building more complex examples, we can specify certain interfaces as such:

impl<T: Serial> Modem for T {}

or

impl<S: Serial + Async> Terminal for S {}

As an aside, I would love to develop the teensy3 APIs along side something like the f3 crate, to show how portable Rust can make embedded code. Right now, it is more or less just a proof of concept. The Arduino is a huge success for many reasons, but a hard-defined abstraction layer has absolutely helped that ecosystem (you can take the same code written 5 years ago for an AVR micro, and port it with zero effort to an ARM Cortex M3 - e.g. the Teensy3).

jamesmunns commented Nov 6, 2016

Hey, sorry to show up late to the party. @thejpster and @japaric you have both hit some really good points here, but I thought I could weigh in on the trait based API.

Since we have traits and composition here, I think the best thing we can do is define the minimum common behavior, and build out functionality based on that.

Using the Serial example, we may come to agreement that this includes something like:

trait Serial {
  fn read(&self) -> Option<u8>;
  fn write(&self, u8) -> Result<(), ()>;
}

It doesn't cover how this is implemented, but allows us to define a common denominator, which can then be composed into more and more complex (or more and more specific) kinds of interfaces. Sometimes blocking will be right, sometimes FIFO-backed non-blocking will be right, sometimes callbacks will be right.

This could be implemented by many kinds of Serial, such as AsyncSerial, BlockingSerial, CallbackSerial, etc. I think the defining characteristic of embedded development is that there is no single abstraction that works for all cases (based on size, speed, etc). Since we can use trait specialization at compile time, this helps remove ambiguity at "zero cost".

Later, when building more complex examples, we can specify certain interfaces as such:

impl<T: Serial> Modem for T {}

or

impl<S: Serial + Async> Terminal for S {}

As an aside, I would love to develop the teensy3 APIs along side something like the f3 crate, to show how portable Rust can make embedded code. Right now, it is more or less just a proof of concept. The Arduino is a huge success for many reasons, but a hard-defined abstraction layer has absolutely helped that ecosystem (you can take the same code written 5 years ago for an AVR micro, and port it with zero effort to an ARM Cortex M3 - e.g. the Teensy3).

@jamesmunns

This comment has been minimized.

Show comment
Hide comment
@jamesmunns

jamesmunns Nov 6, 2016

Expanding a little on my last example, I thought I would write a little more pseudocode.

struct FifoSerial {
// some fields omitted
}

impl Serial for FifoSerial {
  fn read(&mut self) -> Option<u8> {
    self.rd_fifo.pop()
  }

  fn write(&mut self, data: u8) -> Result<(), ()> {
    self.wr_fifo.push(data)
  }
}

// Marker trait used as a tag
impl Nonblocking for FifoSerial {};

fn forward<I: Serial, O: Serial+Nonblocking>(in: I, out: O) -> Result<(), ()> {
  // Take from a high priority port to a low priority, memory backed port
  if Some(b) = in.read() {
    try!(out.write(b));
  }
  Ok(())
}

jamesmunns commented Nov 6, 2016

Expanding a little on my last example, I thought I would write a little more pseudocode.

struct FifoSerial {
// some fields omitted
}

impl Serial for FifoSerial {
  fn read(&mut self) -> Option<u8> {
    self.rd_fifo.pop()
  }

  fn write(&mut self, data: u8) -> Result<(), ()> {
    self.wr_fifo.push(data)
  }
}

// Marker trait used as a tag
impl Nonblocking for FifoSerial {};

fn forward<I: Serial, O: Serial+Nonblocking>(in: I, out: O) -> Result<(), ()> {
  // Take from a high priority port to a low priority, memory backed port
  if Some(b) = in.read() {
    try!(out.write(b));
  }
  Ok(())
}
@jamesmunns

This comment has been minimized.

Show comment
Hide comment
@jamesmunns

jamesmunns Nov 6, 2016

I've opened a separate RFC here, since I feel like I am being too specific for this thread :). See here: rust-embedded/wg#19

I've opened a separate RFC here, since I feel like I am being too specific for this thread :). See here: rust-embedded/wg#19

@skade

This comment has been minimized.

Show comment
Hide comment
@skade

skade Nov 9, 2016

Contributor

Hm, I still don't have a proper "shopping list" :). Can someone pick one or more retailers for me, give me a rough quote and tell me which items to buy (and exactly how many) and where to send them?

Please shoot a bit high, if I cannot fulfill, I'll just deduce some items.

Contributor

skade commented Nov 9, 2016

Hm, I still don't have a proper "shopping list" :). Can someone pick one or more retailers for me, give me a rough quote and tell me which items to buy (and exactly how many) and where to send them?

Please shoot a bit high, if I cannot fulfill, I'll just deduce some items.

@thejpster

This comment has been minimized.

Show comment
Hide comment
@thejpster

thejpster Nov 18, 2016

Contributor

Apologies I didn't get this sorted earlier. Cambridge Consultants is now officially on, so I'll bring a bunch of boards down from my personal stash. I have a TI Stellaris Launchpad, two Freescale Kinetis KE06Zs, and one or two TI Tiva-C Connected Launchpads (the ones with Ethernet).

What's the mechanism for co-ordinating all the groups on the day? IRC? WebEx?

Contributor

thejpster commented Nov 18, 2016

Apologies I didn't get this sorted earlier. Cambridge Consultants is now officially on, so I'll bring a bunch of boards down from my personal stash. I have a TI Stellaris Launchpad, two Freescale Kinetis KE06Zs, and one or two TI Tiva-C Connected Launchpads (the ones with Ethernet).

What's the mechanism for co-ordinating all the groups on the day? IRC? WebEx?

@skade

This comment has been minimized.

Show comment
Hide comment
@skade

skade Nov 18, 2016

Contributor

IRC and then anything the group would like.

On 18 Nov 2016, at 12:06, thejpster notifications@github.com wrote:

Apologies I didn't get this sorted earlier. Cambridge Consultants is now officially on, so I'll bring a bunch of boards down from my personal stash. I have a TI Stellaris Launchpad, two Freescale Kinetis KE06Zs, and one or two TI Tiva-C Connected Launchpads (the ones with Ethernet).

What's the mechanism for co-ordinating all the groups on the day? IRC? WebEx?


You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.

Contributor

skade commented Nov 18, 2016

IRC and then anything the group would like.

On 18 Nov 2016, at 12:06, thejpster notifications@github.com wrote:

Apologies I didn't get this sorted earlier. Cambridge Consultants is now officially on, so I'll bring a bunch of boards down from my personal stash. I have a TI Stellaris Launchpad, two Freescale Kinetis KE06Zs, and one or two TI Tiva-C Connected Launchpads (the ones with Ethernet).

What's the mechanism for co-ordinating all the groups on the day? IRC? WebEx?


You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment