Skip to content
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

Proposal: add DMA support to SPI #342

Draft
wants to merge 6 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions content/docs/guides/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ For **Debian** or **Ubuntu** you can install LLVM by adding a new apt repository
| Debian | sid | `unstable`|

```shell
echo 'deb http://apt.llvm.org/xxxxx/ llvm-toolchain-xxxxx-15 main' | sudo tee /etc/apt/sources.list.d/llvm.list
echo 'deb http://apt.llvm.org/xxxxx/ llvm-toolchain-xxxxx-16 main' | sudo tee /etc/apt/sources.list.d/llvm.list
```

After adding the apt repository for your distribution you may install the LLVM toolchain packages:
Expand All @@ -63,13 +63,13 @@ sudo apt-get install clang-16 llvm-16-dev lld-16 libclang-16-dev
For **MacOS**, you can install LLVM through [Homebrew](https://formulae.brew.sh/formula/llvm). The Clang/LLVM version from Apple is not supported by TinyGo.

```shell
brew install llvm
brew install llvm@16
```

For **Fedora** users you can install LLVM from the repository. Note that the version of LLVM [varies by Fedora version](https://packages.fedoraproject.org/pkgs/llvm/llvm-libs/), for example Fedora 37 has LLVM 15.

```shell
sudo dnf install llvm-devel lld-libs lld
sudo dnf install llvm-devel clang-libs lld
```

After LLVM has been installed, installing TinyGo should be as easy as running the following command:
Expand All @@ -90,7 +90,7 @@ If you are getting a build error like this, LLVM is not installed as expected:
1 error generated.
```

This can often be fixed by specifying the LLVM version as a build tag, for example `-tags=llvm14` if you have LLVM 14 instead of LLVM 16.
This can often be fixed by specifying the LLVM version as a build tag, for example `-tags=llvm15` if you have LLVM 15 instead of LLVM 16.

Note that you should not use `make` when you want to build using a system-installed LLVM, just use the Go toolchain. `make` is used when you want to use a self-built LLVM, as in the next section.

Expand Down
32 changes: 32 additions & 0 deletions content/docs/reference/machine.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,30 @@ The `Tx` performs the actual SPI transaction, and return an error if there was a

Some chips may also support mismatched lengths of `w` and `r`, in which case they will behave like above for the remaining bytes in the byte slice that's the longest of the two.

```go
func (spi SPI) IsAsync() bool
```

Return whether the SPI supports asynchronous operation (usually using [DMA](https://en.wikipedia.org/wiki/Direct_memory_access)). Asynchronous operation may be supported for some or all transfers, for example it may only be supported for send-only transfers.

```go
func (spi SPI) StartTx(w, r []byte) error
```

Start a SPI transmission in the background (usually, using DMA). This has the same effect as running `Tx` in a goroutine, but doesn't spawn a new goroutine. The `w` and `r` byte slices must not be used while the transmission is in progress, but must be stored somewhere outside the `StartTx` function to avoid garbage collecting them.

It is allowed to start multiple transactions without waiting for the first to finish. They will have the effect as if `Tx` was called multiple times in sequence. Lots of hardware won't support this however and will simply wait for the first to finish before starting a new transmission.

If `IsAsync` returns false, this is an alias for `Tx`.

```go
func (spi SPI) Wait() error
```

Wait until all active transactions (started by `StartTx`) have finished. The buffers provided in `StartTx` will be available after calling `Wait`.

If `IsAsync` returns false, this is a no-op.


## I2C

Expand Down Expand Up @@ -365,6 +389,14 @@ CPUReset performs a hard system reset.

Not all chips support CPUReset.

```go
func DeviceID() []byte
```

DeviceID returns a byte array containing a unique id (aka Serial Number) specific to this chip. In some architectures (notably RP2040) the device ID is actually the ID of the flash chip. The device ID can be useful for identifying specific devices within a family. There is no guarantee the ID is globally unique. The size of the ID is chip-family specific with 8 bytes (64 bits) and 16 bytes (128 bits) being common.

Not all chips have a hardware ID.

```go
func GetRNG() uint32
```
Expand Down
21 changes: 17 additions & 4 deletions imports/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,13 @@ import (
"text/template"
)

const (
testGOOS = "linux"
testGOARCH = "amd64"
)

// The environment to pass to `go` commands when they are invoked.
var commandEnv = []string{"GOPATH=/does-not-exist", "GO111MODULE=off"}
var commandEnv = []string{"GOPATH=/does-not-exist", "GO111MODULE=off", "GOOS=" + testGOOS, "GOARCH=" + testGOARCH}

var markdownTemplate = template.Must(template.New("markdown").Parse(`
---
Expand All @@ -24,11 +29,13 @@ The following table shows all Go standard library packages and whether they can

Note that the fact they can be imported, does not mean that all functions and types in the program can be used. For example, sometimes using some functions or types of the package will still trigger compiler errors.

Test results are for {{.goos}}/{{.goarch}}.

Package | Importable | Passes tests
--- | --- | --- |{{ range .}}
--- | --- | --- |{{ range .pkgs}}
{{.Path}} | {{if .CanBeCompiled}} <span style="color: green">✔</span> yes {{else}} [<span style="color: red">✗</span> no](#{{.Link}}) {{end}} | {{if .PassesTests}} <span style="color: green">✔</span> yes {{else if .CanBeCompiled}} [<span style="color: red">✗</span> no](#{{.Link}}) {{else}} <span style="color: gray">✗</span> no {{end}} | {{ end }}

{{range .}}
{{range .pkgs}}
{{if not .PassesTests }}
## {{.Path}}

Expand Down Expand Up @@ -234,7 +241,11 @@ func checkPackages(goroot string) error {
}

// Print the output to stdout.
return markdownTemplate.Execute(os.Stdout, pkgMap)
return markdownTemplate.Execute(os.Stdout, map[string]interface{}{
"pkgs": pkgMap,
"goos": testGOOS,
"goarch": testGOARCH,
})
}

func (pkg *Package) runTest() (result testResult) {
Expand All @@ -252,6 +263,7 @@ func (pkg *Package) runTest() (result testResult) {

// Run the compile test.
cmd := exec.Command("tinygo", "build", "-o", temporaryExecutableFile, temporaryGoFile)
cmd.Env = append(cmd.Environ(), "GOOS="+testGOOS, "GOARCH="+testGOARCH)
buf := new(bytes.Buffer)
cmd.Stdout = buf
cmd.Stderr = buf
Expand All @@ -261,6 +273,7 @@ func (pkg *Package) runTest() (result testResult) {
// Run the actual test.
if result.compiles {
cmd := exec.Command("tinygo", "test", pkg.Path)
cmd.Env = append(cmd.Environ(), "GOOS="+testGOOS, "GOARCH="+testGOARCH)
buf := new(bytes.Buffer)
cmd.Stdout = buf
cmd.Stderr = buf
Expand Down