Skip to content

Commit

Permalink
pbdrv/block_device: Implement async program load and save.
Browse files Browse the repository at this point in the history
This replaces the polling SPI implementation (deactivated in the
previous commit) with asynchronous DMA driven SPI transfers.
This fixes motors going out of sync when starting programs.

Fixes pybricks/support#679

This also avoids touching file systems used by other known firmwares,
so that Pybricks can operate entirely stand alone. This reduces
the complexity of firmware installation and troubleshooting, because
there are no dependencies on prior firmwares or hub state.

It also lays the groundwork for saving and storing program data on
Powered Up hubs, which can be implemented in a future commit.
  • Loading branch information
laurensvalk committed Aug 26, 2022
1 parent 37e6969 commit e13c12a
Show file tree
Hide file tree
Showing 25 changed files with 1,148 additions and 11 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,30 @@
### Changed
- Battery full indication (green light) comes on earlier ([support#647]).
- New indication for over-charging battery (blinking green light).
- On Move Hub, City Hub, and Technic Hub, programs can now be restarted with
the button after downloading them. After reboot, it still falls back to the
program stored in the firmware.
- Improved program download process. Reduces the likelihood of getting errors
about incompatible .mpy files when accidentally entering characters in the
terminal window when no program is active.
- On Prime Hub and Essential Hub, there is no longer a wait time after boot
before you can start programs.
- On Prime Hub and Essential Hub, the user program is now stored in a section
of the external flash that is not used by any file system of other known
firmwares, in order to avoid compatibility issues when changing firmware.

### Fixed
- Fixed motors going out of synch when starting program ([support#679]).
- Fixed city hub turning back on after shutdown ([support#692]).
- Fixed IMU I2C bus lockup on SPIKE hubs ([support#232]).
- Fixed REPL history corrupt after soft reset ([support#699]).
- Fixed "ValueError: incompatible .mpy file" when pressing the button when
there is no program yet ([support#599]).

[support#232]: https://github.com/pybricks/support/issues/232
[support#232]: https://github.com/pybricks/support/issues/599
[support#647]: https://github.com/pybricks/support/issues/647
[support#699]: https://github.com/pybricks/support/issues/679
[support#692]: https://github.com/pybricks/support/issues/692
[support#699]: https://github.com/pybricks/support/issues/699

Expand Down
6 changes: 6 additions & 0 deletions bricks/essentialhub/essential_hub.ld
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,10 @@ MEMORY

"FW_INFO_OFFSET" = 0x200;
_stack_size = 16K;

/**
* External flash storage size for 1 application program. The full user program
* is loaded into RAM to run it, so the storage must not be bigger than RAM.
* We also need to allow some RAM for bss and heap, so set storage a bit lower.
*/
_pbdrv_block_device_storage_size = 256K;
6 changes: 6 additions & 0 deletions bricks/primehub/prime_hub.ld
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,10 @@ MEMORY
}

_stack_size = 16K;

/**
* External flash storage size for 1 application program. The full user program
* is loaded into RAM to run it, so the storage must not be bigger than RAM.
* We also need to allow some RAM for bss and heap, so set storage a bit lower.
*/
_pbdrv_block_device_storage_size = 256K;
2 changes: 2 additions & 0 deletions bricks/stm32/stm32.mk
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,8 @@ PBIO_SRC_C = $(addprefix lib/pbio/,\
drv/adc/adc_stm32_hal.c \
drv/adc/adc_stm32f0.c \
drv/battery/battery_adc.c \
drv/block_device/block_device_flash_stm32.c \
drv/block_device/block_device_w25qxx_stm32.c \
drv/bluetooth/bluetooth_btstack_control_gpio.c \
drv/bluetooth/bluetooth_btstack_run_loop_contiki.c \
drv/bluetooth/bluetooth_btstack_uart_block_stm32_hal.c \
Expand Down
23 changes: 23 additions & 0 deletions lib/pbio/drv/block_device/block_device.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors

#ifndef _INTERNAL_PBDRV_BLOCK_DEVICE_H_
#define _INTERNAL_PBDRV_BLOCK_DEVICE_H_

#include <stdint.h>

#include <pbdrv/config.h>
#include <pbio/error.h>

#if PBDRV_CONFIG_BLOCK_DEVICE

void pbdrv_block_device_init(void);

#else // PBDRV_CONFIG_BLOCK_DEVICE

static inline void pbdrv_block_device_init(void) {
}

#endif // PBDRV_CONFIG_BLOCK_DEVICE

#endif // _INTERNAL_PBDRV_BLOCK_DEVICE_H_
62 changes: 62 additions & 0 deletions lib/pbio/drv/block_device/block_device_flash_stm32.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors

// Block device driver for Internal_flash.

#include <pbdrv/config.h>

#if PBDRV_CONFIG_BLOCK_DEVICE_FLASH_STM32

#include <stdint.h>
#include <string.h>

#include <contiki.h>

#include "../core.h"

#include <pbdrv/block_device.h>

#include <pbio/error.h>
#include <pbio/util.h>

uint32_t pbdrv_block_device_get_size(void) {
// Defined in linker script.
extern uint32_t _pbdrv_block_device_storage_size;
return (uint32_t)(&_pbdrv_block_device_storage_size);
}

void pbdrv_block_device_init(void) {
}

void pbdrv_block_device_set_callback(void (*callback)(void)) {
}

PT_THREAD(pbdrv_block_device_read(struct pt *pt, uint32_t offset, uint8_t *buffer, uint32_t size, pbio_error_t *err)) {

PT_BEGIN(pt);

// TODO: Read from user flash. For now this just loads
// the mpy file appended to the firmware to keep Pybricks Code working.
extern uint32_t _pb_user_mpy_size;
if (_pb_user_mpy_size + 8 > pbdrv_block_device_get_size()) {
*err = PBIO_ERROR_FAILED;
PT_EXIT(pt);
}
extern uint8_t _pb_user_mpy_data[];
pbio_set_uint32_le(buffer, _pb_user_mpy_size + 8);
pbio_set_uint32_le(&buffer[4], _pb_user_mpy_size);
memcpy(&buffer[8], _pb_user_mpy_data, _pb_user_mpy_size);
*err = PBIO_SUCCESS;

PT_END(pt);
}

PT_THREAD(pbdrv_block_device_store(struct pt *pt, uint8_t *buffer, uint32_t size, pbio_error_t *err)) {

PT_BEGIN(pt);
// TODO: Implement saving to user flash.
*err = PBIO_ERROR_NOT_IMPLEMENTED;
PT_END(pt);
}

#endif // PBDRV_CONFIG_BLOCK_DEVICE_FLASH_STM32
Loading

0 comments on commit e13c12a

Please sign in to comment.