firmware merge requestshttps://git.flow3r.garden/card10/firmware/-/merge_requests2021-07-25T22:02:27Zhttps://git.flow3r.garden/card10/firmware/-/merge_requests/474Disable core 1 interrupts during API calls2021-07-25T22:02:27Zrahixcard10@rahix.deDisable core 1 interrupts during API calls@schneider, this is for you :) I _think_ I've managed to figure out how to solve the lockup you observed in a way that's both compatible with the old (non-masking API calls) and new (irq-masking API calls) schemes. Please take a close ...@schneider, this is for you :) I _think_ I've managed to figure out how to solve the lockup you observed in a way that's both compatible with the old (non-masking API calls) and new (irq-masking API calls) schemes. Please take a close look though, I'm a bit scared that I might have again missed something here...
Commit 7fb481780ac0 ("feat(lifecycle): Allow core 1 to disable interrupts during API calls") is the important part. The commit message explains the details:
> When interrupts are disabled during API calls on core 1, we can only trigger a core 1 reset when there is no API call ongoing. This means that the lifecycle machinery needs to allow any running API calls to complete before it has a chance to see its reset interrupt delivered.
>
> This is complicated because we cannot synchronize on core 1 triggering an API call - the best we can do is stop the dispatcher, check whether our reset interrupt was delivered, and if not, give it another chance to process an API call.
>
> Additionally, "give it another chance to process an API call" means that the IDLE task must run, because this is currently a prerequisite to scheduling the dispatcher (see [API call mechanism](https://firmware.card10.badge.events.ccc.de/epicardium/overview.html#internals)). The only way to facilitate this is with a sleep that is long enough that it will eventually let core 0 go idle. It seems that an 8 tick delay does the job quite fine.
>
> Thus, implement a busy loop which provides the above requirements and with that makes Epicardium prepared for payloads which perform API calls with interrupts disabled.
Ontop, I then added the critical section in the API caller code in commit 927411099163 ("feat(api-caller): Hard-disable all IRQs during API calls"). Note that I am currently disabling absolutely everything here - we might want to revise this in the future to allow some kind of "NMI execution stage" which can still run but then cannot call API calls. Doing this would break the sleep-usecase again, though...schneiderschneiderhttps://git.flow3r.garden/card10/firmware/-/merge_requests/380BSEC support2020-12-24T21:39:59ZschneiderBSEC supportAdds basic Bosch BSEC support.
BSEC is a proprietary library from Bosch which uses the BME680 to calculate an estimation of an "Indoor Air Quality". It takes complete control of the BME680 and performs a measurement every 3 seconds. Thi...Adds basic Bosch BSEC support.
BSEC is a proprietary library from Bosch which uses the BME680 to calculate an estimation of an "Indoor Air Quality". It takes complete control of the BME680 and performs a measurement every 3 seconds. This consumes about 0.9 mA on the 1.8 V rail. A later iteration of this driver might also allow to change the interval to 300 seconds to save energy.
Two configuration options are introduced. One to enable the driver (as it is a binary blob) and one to enable the debug prints of the driver. If the library is active, calls to the BME680 API will stop using the sensor directly and return a subset of the data gathered by the BSEC library.
You can use this https://phyphox.org/ "experiment" to access the data:
![download__1_](/uploads/c5fc1dfc1189e56491730c21b2ee2bf2/download__1_.png)
![cwNiWbhBMDGanPdkseSkGBCn](/uploads/d6d4fed5084a53e2398a7f1087218575/cwNiWbhBMDGanPdkseSkGBCn.png)
In addition the pycardium BME680 API and the BLE Environmental Sensing Service have been extended.https://git.flow3r.garden/card10/firmware/-/merge_requests/96Changes for the Cycle of Life [MANUAL MERGE]2019-08-15T23:06:58Zrahixcard10@rahix.deChanges for the Cycle of Life [MANUAL MERGE]Finally ... This is quite a big changeset, so I tried to make sure to separate
the changes into individual commits. **Please don't squash!!**
Please don't merge before everyone had the chance to take a look; these changes
go quite ...Finally ... This is quite a big changeset, so I tried to make sure to separate
the changes into individual commits. **Please don't squash!!**
Please don't merge before everyone had the chance to take a look; these changes
go quite deep into a lot of parts of the firmware and I fear I might have
accidentally broken some things ...
**WARNING**: These changes break the API (hopefully for the last time ...)
---
Here's what's included:
### 6e2d34915c8ebd1be7845a1b57442ddf41c6da14 fix(l0dables): Fix vector table alignment
The vector table's alignment requirements depend on the number of interrupts
([Cortex-M4 VTOR](https://developer.arm.com/docs/dui0553/a/cortex-m4-peripherals/system-control-block/vector-table-offset-register)).
In our case, we have `0x6E`(=110) interrupts and thus an alignment requirement
of `0x80`(=128).
To satisfy this requirement, this commit moves the IVT to the beginning of
`.text` and enforces a 128 byte alignment. Please note that the headers which
come before `.text` will push the IVT to `0x100` instead of having it directly
in the beginning at `0x00`.
@q3k, remember when I told you? :P
### 6510d8dd4ffdf27ac9f046deaff680706ef4438d feat(epicardium): Add switch for core 1 debugging
You can enable core 1 debugging by bootstrapping with
```bash
./bootstrap.sh -Ddebug_core1=true
```
### 904851ab748bedbbaa86854d3441de330317eb15 fix(api): Fix API overlapping core 1 stack
Core 1 has its stack base at `0x20080000` which would overlap with the first
byte of the API parameter space. This patch moves the API further back to
prevent any weird behaviours being caused by this.
### 6cd4fcc36d9aecbcec1e002328db508928e7c383 feat(api): Add initial argument passing
This allows Pycardium to learn which script it should start once it
boots. Arguments can only be read before any API calls are made.
Afterward they are lost.
To ensure they won't collide with anything during a core 1 restart,
they are offset by `0x20` from the start of the API buffer.
### 78a7e827d6ac0fb7a6a1cdb6a2a7eb9888219c88 fix(api): Change interrupt idle value to ``-1``
Previously `0` was used but as `0` is also the ID of the reset interrupt,
this could lead to weird behaviors.
### 1b8b490bc2311ea7dab609b06f704af163eeb5d3 fix(api): Make reset interrupt non-maskable
### 98be0bcee0dab5ba9b4c4189615e78c35fc39fd9 feat(epicardium): Implement basic core 1 lifecycle
This commit introduces a way to control core 1. This is archieved by a
predefined API-Interrupt: The reset interrupt. When triggered, it will
bring the core back into its default state and wait for a new vector
address from Epicardium. Once this vector address is transferred, it
will start the new payload.
This method only works as long as core 1 is responsive to the API
interrupts. Cases where this might not be the case:
- During times where core 1 has interrupts disabled
- When in a higher priority exception handler
- When core 1 has corrupted its IVT
### bb54b68b6ea5fdb1820ac87ef0ef386098bb444c chore(epicardium): Move dispatcher into own module
Also add a mutex around API calls in preparation for future changes.
### 37daca63a65be158a0e28cef08acca90bdbd6d7b feat(epicardium): Add module for hardware init
Hardware initialization routines should not clutter main and instead belong
into the new `epicardium/modules/hardware.c`. Haven't moved anything yet,
though.
Also splits the init into two steps, `hardware_early_init()` which runs before
absolutely everything and `hardware_init()` for less critical stuff.
### c7be004eda2cb192562fd3844bd6a6877f8fbe2f feat(epicardium): Add core 1 lifecycle
This commit introduces a lifecycle for core 1. Based on the new loading
system, a few APIs are made available to control the payload running on
core 1. These are:
1. From core 1 (Pycardium, L0dable):
- `epic_exec(name)` API Call: Request loading of a new payload by
name. If the file does not exist, the call will return with an
error code. Otherwise, control will go to the new payload.
- `epic_exit(retcode)` API Call: Return from payload
unconditionally. This call should be called whenever a payload is
done or when it has hit an unrecoverable error. On `epic_exit`,
Epicardium will reset the core back into the menu.
2. From inside Epicardium:
- `epic_exec(name)`: This is **not** the same as the API call, as it
needs a different implementation underneath. It will load a new
payload and wait until this load actually completed (synchroneous).
- `return_to_menu()`: Return core 1 to the menu script no matter
what it is currently doing. This call is asynchroneous and will
return immediately after scheduling the lifecycle task. This task
will then take care of actually performing the load.
### 632f3652bf0091869bd1adab6c762c70c58c5fdc feat(pycardium): Add a barebones "os" module
Provides `os.exit(ret)` and `os.exec("file.py")`.
### d5da536f0d8f4a6a187188b37471883b6cb8f7f8 feat(pycardium): Return on HardFault
When Pycardium encounters a HardFault, it will now return to the menu.
### b1371bb67b20049ac98a76464c5a74a991fa6288 feat(pmic): Implement proper reset behavior
Pressing the power button will now excert the following behavior:
- `<400 ms`: Return back to menu
- `<1 s`: Reset card10
- `>1 s`: Poweroff
cc @schneider, @q3k, @swymhttps://git.flow3r.garden/card10/firmware/-/merge_requests/27Autogenerate IRQ stubs2019-07-21T19:03:38Zrahixcard10@rahix.deAutogenerate IRQ stubsschneiderschneiderhttps://git.flow3r.garden/card10/firmware/-/merge_requests/18Python interrupts2019-07-20T19:38:59ZschneiderPython interruptsPoC towards #35PoC towards #35