* Add Flash::totalSize() method

* Fix doc comment

* Move JACDAC timer to core

* Add support for NRF52

* Don't panic on missing button config (happens on maker)
This commit is contained in:
Michał Moskal 2020-01-31 17:49:55 -08:00 коммит произвёл GitHub
Родитель 4e9abf5c77
Коммит d411cee039
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
19 изменённых файлов: 1968 добавлений и 35 удалений

Просмотреть файл

@ -1,8 +1,4 @@
#include "pxtbase.h"
#ifdef CODAL_JACDAC_WIRE_SERIAL
#include "LowLevelTimer.h"
using namespace codal;
#endif
#include <limits.h>
#include <stdlib.h>
@ -1502,20 +1498,6 @@ void deepSleep() __attribute__((weak));
//%
void deepSleep() {}
#ifdef CODAL_JACDAC_WIRE_SERIAL
LowLevelTimer *getJACDACTimer() {
static LowLevelTimer *jacdacTimer;
if (!jacdacTimer) {
jacdacTimer = allocateTimer();
jacdacTimer->setIRQPriority(1);
}
return jacdacTimer;
}
void initSystemTimer() {
new CODAL_TIMER(*allocateTimer());
}
#endif
int *getBootloaderConfigData() __attribute__((weak));
int *getBootloaderConfigData() {
return NULL;

Просмотреть файл

@ -994,10 +994,6 @@ extern "C" void *app_alloc(int numbytes);
extern "C" void *app_free(void *ptr);
void gcPreAllocateBlock(uint32_t sz);
#ifdef CODAL_JACDAC_WIRE_SERIAL
codal::LowLevelTimer *allocateTimer();
#endif
#ifdef PXT64
#define TOWORDS(bytes) (((bytes) + 7) >> 3)
#else

1189
libs/core---nrf52/dal.d.ts поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

33
libs/core---nrf52/enums.d.ts поставляемый Normal file
Просмотреть файл

@ -0,0 +1,33 @@
// Auto-generated. Do not edit.
declare const enum PulseValue {
//% block=high
High = 4, // DEVICE_PIN_EVT_PULSE_HI
//% block=low
Low = 5, // DEVICE_PIN_EVT_PULSE_LO
}
declare const enum PinEvent {
//% block="pulse high"
PulseHigh = 4, // DEVICE_PIN_EVT_PULSE_HI
//% block="pulse low"
PulseLow = 5, // DEVICE_PIN_EVT_PULSE_LO
//% block="rise"
Rise = 2, // DEVICE_PIN_EVT_RISE
//% block="fall"
Fall = 3, // DEVICE_PIN_EVT_FALL
}
declare const enum PinPullMode {
//% block="down"
PullDown = 0,
//% block="up"
PullUp = 1,
//% block="none"
PullNone = 2,
}
// Auto-generated. Do not edit. Really.

Просмотреть файл

@ -0,0 +1,137 @@
#include "pxt.h"
#include "NRFLowLevelTimer.h"
namespace pxt {
struct TimerConfig {
uint8_t id;
IRQn_Type irqn;
NRF_TIMER_Type *addr;
};
#define DEF_TIM(n) \
{ 0x10 + n, TIMER##n##_IRQn, NRF_TIMER##n }
static const TimerConfig timers[] = {
#ifdef NRF_TIMER0
DEF_TIM(0),
#endif
#ifdef NRF_TIMER1
DEF_TIM(1),
#endif
#ifdef NRF_TIMER2
DEF_TIM(2),
#endif
#ifdef NRF_TIMER3
DEF_TIM(3),
#endif
#ifdef NRF_TIMER4
DEF_TIM(4),
#endif
#ifdef NRF_TIMER5
DEF_TIM(5),
#endif
#ifdef NRF_TIMER6
DEF_TIM(6),
#endif
{0,(IRQn_Type)0,0}
};
#define DEF_TIMERS 0x11121013 // TIMER1 TIMER2 TIMER0 TIMER3
static uint32_t usedTimers;
static int timerIdx(uint8_t id) {
for (unsigned i = 0; timers[i].id; i++) {
if (id == timers[i].id)
return i;
}
return -1;
}
LowLevelTimer *allocateTimer() {
uint32_t timersToUse = getConfig(CFG_TIMERS_TO_USE, DEF_TIMERS);
for (int shift = 24; shift >= 0; shift -= 8) {
uint8_t tcId = (timersToUse >> shift) & 0xff;
int idx = timerIdx(tcId);
if (idx < 0 || (usedTimers & (1 << idx)))
continue;
auto dev = timers[idx].addr;
if (dev->INTENSET) // any irqs enabled?
continue; // then we won't allocate it
usedTimers |= 1 << idx;
DMESG("allocate TIMER%d", tcId - 0x10);
return new NRFLowLevelTimer(dev, timers[idx].irqn);
}
target_panic(PANIC_OUT_OF_TIMERS);
return NULL;
}
static void initRandomSeed() {
int seed = 0xC0DA1;
/*
auto pinTemp = LOOKUP_PIN(TEMPERATURE);
if (pinTemp)
seed *= pinTemp->getAnalogValue();
auto pinLight = LOOKUP_PIN(LIGHT);
if (pinLight)
seed *= pinLight->getAnalogValue();
*/
seedRandom(seed);
}
#if defined(NRF52840) || defined(NRF52833)
#define IS_3_3_V() ((NRF_UICR->REGOUT0 & 7) == 5)
#else
#define IS_3_3_V() 1
#endif
static void disableNFConPins() {
// Ensure NFC pins are configured as GPIO. If not, update the non-volatile UICR.
if (NRF_UICR->NFCPINS || !IS_3_3_V()) {
DMESG("RESET UICR\n");
// Enable Flash Writes
NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos);
while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
;
// Configure PINS for GPIO use.
if (NRF_UICR->NFCPINS)
NRF_UICR->NFCPINS = 0;
#if defined(NRF52840) || defined(NRF52833)
// Set VDD to 3.3V
if ((NRF_UICR->REGOUT0 & 7) != 5)
NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~7) | 5;
#endif
// Disable Flash Writes
NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);
while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
;
// Reset, so the changes can take effect.
NVIC_SystemReset();
}
}
void platform_init() {
initRandomSeed();
disableNFConPins(); // this is needed when P0_9 and P0_10 are to be used as regular pins
/*
if (*HF2_DBG_MAGIC_PTR == HF2_DBG_MAGIC_START) {
*HF2_DBG_MAGIC_PTR = 0;
// this will cause alignment fault at the first breakpoint
globals[0] = (TValue)1;
}
*/
}
} // namespace pxt
void cpu_clock_init() {
// missing in Codal
}

Просмотреть файл

@ -0,0 +1,126 @@
#ifndef __PXT_PLATFORM_H
#define __PXT_PLATFORM_H
#include "Image.h"
#include "NRF52Microphone.h"
#include "NRF52SPI.h"
#include "NRF52I2C.h"
#include "NRF52Pin.h"
#include "NRF52PWM.h"
#include "Timer.h"
#include "MultiButton.h"
#define PAGE_SIZE 4096
#if defined(NRF52840) || defined(NRF52833)
#define DEV_NUM_PINS 48
#else
#define DEV_NUM_PINS 32
#endif
#define DEV_PWM_PINS 0x0000ffffffffULL // all pins are PWM pins it seems
#define DEV_AIN_PINS 0x0000f000001fULL
// Codal doesn't yet distinguish between PWM and AIN
#define DEV_ANALOG_PINS (DEV_PWM_PINS | DEV_AIN_PINS)
#define CODAL_PIN NRF52Pin
#define CODAL_SPI NRF52SPI
#define CODAL_I2C NRF52I2C
#define CODAL_TIMER Timer
#define IMAGE_BITS 4
typedef uint8_t PinName;
#define neopixel_send_buffer(pin, ptr, len) target_panic(50)
#define DEFAULT_NEOPIXEL_PIN P0_0
// The parameters below needs tuning!
/*
* @param nominalValue The value (in SI units) of a nominal position.
* @param nominalReading The raw reading from the sensor at the nominal position.
* @param beta The Steinhart-Hart Beta constant for the device
* @param seriesResistor The value (in ohms) of the resistor in series with the sensor.
* @param zeroOffset Optional zero offset applied to all SI units (e.g. 273.15 for temperature
* sensing in C vs Kelvin).
*/
#define TEMPERATURE_NOMINAL_VALUE 25
#define TEMPERATURE_NOMINAL_READING 10000
#define TEMPERATURE_BETA 3380
#define TEMPERATURE_SERIES_RESISTOR 10000
#define TEMPERATURE_ZERO_OFFSET 273.5
#define LIGHTSENSOR_SENSITIVITY 868 // codal has 912 now
#define LIGHTSENSOR_LOW_THRESHOLD 128
#define LIGHTSENSOR_HIGH_THRESHOLD 896
#define P0_0 0
#define P0_1 1
#define P0_2 2
#define P0_3 3
#define P0_4 4
#define P0_5 5
#define P0_6 6
#define P0_7 7
#define P0_8 8
#define P0_9 9
#define P0_10 10
#define P0_11 11
#define P0_12 12
#define P0_13 13
#define P0_14 14
#define P0_15 15
#define P0_16 16
#define P0_17 17
#define P0_18 18
#define P0_19 19
#define P0_20 20
#define P0_21 21
#define P0_22 22
#define P0_23 23
#define P0_24 24
#define P0_25 25
#define P0_26 26
#define P0_27 27
#define P0_28 28
#define P0_29 29
#define P0_30 30
#define P0_31 31
#define P1_0 32
#define P1_1 33
#define P1_2 34
#define P1_3 35
#define P1_4 36
#define P1_5 37
#define P1_6 38
#define P1_7 39
#define P1_8 40
#define P1_9 41
#define P1_10 42
#define P1_11 43
#define P1_12 44
#define P1_13 45
#define P1_14 46
#define P1_15 47
#define P1_16 48
#define P1_17 49
#define P1_18 50
#define P1_19 51
#define P1_20 52
#define P1_21 53
#define P1_22 54
#define P1_23 55
#define P1_24 56
#define P1_25 57
#define P1_26 58
#define P1_27 59
#define P1_28 60
#define P1_29 61
#define P1_30 62
#define P1_31 63
#endif

Просмотреть файл

@ -0,0 +1,4 @@
{
"name": "core---nrf52",
"additionalFilePath": "../core"
}

342
libs/core---nrf52/shims.d.ts поставляемый Normal file
Просмотреть файл

@ -0,0 +1,342 @@
// Auto-generated. Do not edit.
declare namespace light {
/**
* Send a programmable light buffer to the specified digital pin
* @param data The pin that the lights are connected to
* @param clk the clock line if any
* @param mode the color encoding mode
* @param buf The buffer to send to the pin
*/
//% shim=light::sendBuffer
function sendBuffer(data: DigitalInOutPin, clk: DigitalInOutPin, mode: int32, buf: Buffer): void;
}
declare namespace control {
/**
* Determines if the USB has been enumerated.
*/
//% shim=control::isUSBInitialized
function isUSBInitialized(): boolean;
}
declare namespace pins {
/**
* Get a pin by configuration id (DAL.CFG_PIN...)
*/
//% shim=pins::pinByCfg
function pinByCfg(key: int32): DigitalInOutPin;
/**
* Create a new zero-initialized buffer.
* @param size number of bytes in the buffer
*/
//% shim=pins::createBuffer
function createBuffer(size: int32): Buffer;
/**
* Get the duration of the last pulse in microseconds. This function should be called from a
* ``onPulsed`` handler.
*/
//% help=pins/pulse-duration blockGap=8
//% blockId=pins_pulse_duration block="pulse duration (µs)"
//% weight=19 shim=pins::pulseDuration
function pulseDuration(): int32;
}
declare interface AnalogInPin {
/**
* Read the connector value as analog, that is, as a value comprised between 0 and 1023.
* @param name pin to write to
*/
//% help=pins/analog-read weight=53
//% blockId=device_get_analog_pin block="analog read|pin %name" blockGap="8"
//% blockNamespace=pins
//% parts="photocell" trackArgs=0
//% name.fieldEditor="gridpicker"
//% name.fieldOptions.width=220
//% name.fieldOptions.columns=4 shim=AnalogInPinMethods::analogRead
analogRead(): int32;
}
declare interface AnalogOutPin {
/**
* Set the connector value as analog. Value must be comprised between 0 and 1023.
* @param name pin name to write to
* @param value value to write to the pin between ``0`` and ``1023``. eg:1023,0
*/
//% help=pins/analog-write weight=52
//% blockId=device_set_analog_pin block="analog write|pin %name|to %value" blockGap=8
//% blockNamespace=pins
//% parts="analogled" trackArgs=0
//% name.fieldEditor="gridpicker"
//% name.fieldOptions.width=220
//% name.fieldOptions.columns=4
//% value.min=0 value.max=1023 shim=AnalogOutPinMethods::analogWrite
analogWrite(value: int32): void;
}
declare interface DigitalInOutPin {
/**
* Read a pin or connector as either 0 or 1
* @param name pin to read from
*/
//% help=pins/digital-read weight=61
//% blockId=device_get_digital_pin block="digital read|pin %name" blockGap=8
//% parts="slideswitch" trackArgs=0
//% blockNamespace=pins
//% name.fieldEditor="gridpicker"
//% name.fieldOptions.width=220
//% name.fieldOptions.columns=4 shim=DigitalInOutPinMethods::digitalRead
digitalRead(): boolean;
/**
* Set a pin or connector value to either 0 or 1.
* @param name pin to write to
* @param value value to set on the pin
*/
//% help=pins/digital-write weight=60
//% blockId=device_set_digital_pin block="digital write|pin %name|to %value=toggleHighLow"
//% parts="led" trackArgs=0
//% blockNamespace=pins
//% name.fieldEditor="gridpicker"
//% name.fieldOptions.width=220
//% name.fieldOptions.columns=4 shim=DigitalInOutPinMethods::digitalWrite
digitalWrite(value: boolean): void;
/**
* Make this pin a digital input, and create events where the timestamp is the duration
* that this pin was either ``high`` or ``low``.
*/
//% help=pins/on-pulsed weight=16 blockGap=8
//% blockId=pins_on_pulsed block="on|pin %pin|pulsed %pulse"
//% blockNamespace=pins
//% pin.fieldEditor="gridpicker"
//% pin.fieldOptions.width=220
//% pin.fieldOptions.columns=4
//% parts="slideswitch" trackArgs=0
//% deprecated=1 hidden=1 shim=DigitalInOutPinMethods::onPulsed
onPulsed(pulse: PulseValue, body: () => void): void;
/**
* Register code to run when a pin event occurs.
*/
//% help=pins/on-event weight=20 blockGap=8
//% blockId=pinsonevent block="on|pin %pin|%event"
//% blockNamespace=pins
//% pin.fieldEditor="gridpicker"
//% pin.fieldOptions.width=220
//% pin.fieldOptions.columns=4
//% parts="slideswitch" trackArgs=0 shim=DigitalInOutPinMethods::onEvent
onEvent(event: PinEvent, body: () => void): void;
/**
* Return the duration of a pulse in microseconds
* @param name the pin which measures the pulse
* @param value the value of the pulse (default high)
* @param maximum duration in micro-seconds
*/
//% blockId="pins_pulse_in" block="pulse in (µs)|pin %name|pulsed %high||timeout %maxDuration (µs)"
//% weight=18 blockGap=8
//% help="pins/pulse-in"
//% blockNamespace=pins
//% pin.fieldEditor="gridpicker"
//% pin.fieldOptions.width=220
//% pin.fieldOptions.columns=4 maxDuration.defl=2000000 shim=DigitalInOutPinMethods::pulseIn
pulseIn(value: PulseValue, maxDuration?: int32): int32;
/**
* Set the pull direction of this pin.
* @param name pin to set the pull mode on
* @param pull one of the mbed pull configurations: PullUp, PullDown, PullNone
*/
//% help=pins/set-pull weight=17 blockGap=8
//% blockId=device_set_pull block="set pull|pin %pin|to %pull"
//% blockNamespace=pins
//% name.fieldEditor="gridpicker"
//% name.fieldOptions.width=220
//% name.fieldOptions.columns=4 shim=DigitalInOutPinMethods::setPull
setPull(pull: PinPullMode): void;
}
declare interface PwmPin {}
declare interface PwmOnlyPin {
/**
* Set the Pulse-width modulation (PWM) period of the analog output. The period is in
* **microseconds** or `1/1000` milliseconds.
* If this pin is not configured as an analog output (using `analog write pin`), the operation has
* no effect.
* @param name analog pin to set period to
* @param micros period in micro seconds. eg:20000
*/
//% help=pins/analog-set-period weight=51
//% blockId=device_set_analog_period block="analog set period|pin %pin|to (µs)%period"
//% blockNamespace=pins
//% name.fieldEditor="gridpicker"
//% name.fieldOptions.width=220
//% name.fieldOptions.columns=4 shim=PwmOnlyPinMethods::analogSetPeriod
analogSetPeriod(period: int32): void;
/**
* Write a value to the servo to control the rotation of the shaft. On a standard servo, this will
* set the angle of the shaft (in degrees), moving the shaft to that orientation. On a continuous
* rotation servo, this will set the speed of the servo (with ``0`` being full-speed in one
* direction, ``180`` being full speed in the other, and a value near ``90`` being no movement).
* @param name pin to write to
* @param value angle or rotation speed
*/
//% help=pins/servo-write weight=41 group="Servo"
//% blockId=device_set_servo_pin block="servo write|pin %name|to %value=protractorPicker" blockGap=8
//% parts=microservo trackArgs=0
//% blockNamespace=pins
//% name.fieldEditor="gridpicker"
//% name.fieldOptions.width=220
//% name.fieldOptions.columns=4
//% value.defl=90 shim=PwmOnlyPinMethods::servoWrite
servoWrite(value?: int32): void;
/**
* Set the pin for PWM analog output, make the period be 20 ms, and set the pulse width.
* The pulse width is based on the value it is given **microseconds** or `1/1000` milliseconds.
* @param name pin name
* @param duration pulse duration in micro seconds, eg:1500
*/
//% help=pins/servo-set-pulse weight=40 group="Servo" blockGap=8
//% blockId=device_set_servo_pulse block="servo set pulse|pin %value|to (µs) %duration"
//% parts=microservo blockNamespace=pins
//% name.fieldEditor="gridpicker"
//% name.fieldOptions.width=220
//% name.fieldOptions.columns=4 shim=PwmOnlyPinMethods::servoSetPulse
servoSetPulse(duration: int32): void;
}
declare namespace control {
/**
* Announce that an event happened to registered handlers.
* @param src ID of the MicroBit Component that generated the event
* @param value Component specific code indicating the cause of the event.
*/
//% weight=21 blockGap=12 blockId="control_raise_event"
//% help=control/raise-event
//% block="raise event|from %src|with value %value" blockExternalInputs=1 shim=control::raiseEvent
function raiseEvent(src: int32, value: int32): void;
/**
* Determine the version of system software currently running.
*/
//% blockId="control_device_dal_version" block="device dal version"
//% help=control/device-dal-version shim=control::deviceDalVersion
function deviceDalVersion(): string;
/**
* Allocates the next user notification event
*/
//% help=control/allocate-notify-event shim=control::allocateNotifyEvent
function allocateNotifyEvent(): int32;
/** Write a message to DMESG debugging buffer. */
//% shim=control::dmesg
function dmesg(s: string): void;
/** Write a message and value (pointer) to DMESG debugging buffer. */
//% shim=control::dmesgPtr
function dmesgPtr(str: string, ptr: Object): void;
}
declare interface I2C {
/**
* Read `size` bytes from a 7-bit I2C `address`.
*/
//% repeat.defl=0 shim=I2CMethods::readBuffer
readBuffer(address: int32, size: int32, repeat?: boolean): Buffer;
/**
* Write bytes to a 7-bit I2C `address`.
*/
//% repeat.defl=0 shim=I2CMethods::writeBuffer
writeBuffer(address: int32, buf: Buffer, repeat?: boolean): int32;
}
declare namespace pins {
/**
* Opens a Serial communication driver
*/
//% help=pins/create-i2c
//% parts=i2c shim=pins::createI2C
function createI2C(sda: DigitalInOutPin, scl: DigitalInOutPin): I2C;
}
declare namespace pins {
/**
* Opens a SPI driver
*/
//% help=pins/create-spi
//% parts=spi shim=pins::createSPI
function createSPI(mosiPin: DigitalInOutPin, misoPin: DigitalInOutPin, sckPin: DigitalInOutPin): SPI;
}
declare interface SPI {
/**
* Write to the SPI bus
*/
//% shim=SPIMethods::write
write(value: int32): int32;
/**
* Transfer buffers over the SPI bus
*/
//% argsNullable shim=SPIMethods::transfer
transfer(command: Buffer, response: Buffer): void;
/**
* Sets the SPI clock frequency
*/
//% shim=SPIMethods::setFrequency
setFrequency(frequency: int32): void;
/**
* Sets the SPI bus mode
*/
//% shim=SPIMethods::setMode
setMode(mode: int32): void;
}
declare namespace configStorage {
/**
* Puts an entry in the device storage. Key may have up to 16 characters (bytes).
* @param key the identifier (max 16 characters)
* @param value the data (max 32 characters)
*/
//% shim=configStorage::setBuffer
function setBuffer(key: string, value: Buffer): void;
/**
* Gets an entry from the device storage. Key may have up to 16 characters (bytes).
* @param key the identifier (max 16 characters)
*/
//% shim=configStorage::getBuffer
function getBuffer(key: string): Buffer;
/**
* Removes the key from local storage
* @param key the identifier (max 16 characters)
*/
//% shim=configStorage::removeItem
function removeItem(key: string): void;
/**
* Clears the local storage
*/
//% shim=configStorage::clear
function clear(): void;
}
// Auto-generated. Do not edit. Really.

Просмотреть файл

@ -1,4 +1,6 @@
#include "pxt.h"
#include "LowLevelTimer.h"
using namespace codal;
void cpu_clock_init(void);
@ -251,4 +253,16 @@ void gcProcessStacks(int flags) {
xfree(fibers);
}
LowLevelTimer *getJACDACTimer() {
static LowLevelTimer *jacdacTimer;
if (!jacdacTimer) {
jacdacTimer = allocateTimer();
jacdacTimer->setIRQPriority(1);
}
return jacdacTimer;
}
void initSystemTimer() {
new CODAL_TIMER(*allocateTimer());
}
} // namespace pxt

Просмотреть файл

@ -1,6 +1,6 @@
#include "pxt.h"
#ifdef NRF52
#if defined(NRF52_SERIES)
#define _estack __StackTop
#endif
extern uint32_t _estack;

Просмотреть файл

@ -82,6 +82,8 @@ typedef pins::CodalI2CProxy* I2C_;
typedef pins::CodalSPIProxy* SPI_;
namespace pxt {
codal::LowLevelTimer *allocateTimer();
#ifdef CODAL_I2C
CODAL_I2C* getI2C(DigitalInOutPin sda, DigitalInOutPin scl);
#endif

Просмотреть файл

@ -26,7 +26,7 @@ namespace pins {
}
/**
* Write a given command to SPI bus, and afterwards read the response.
* Write a given command to SPI bus, and at the same time read the response.
*/
//% help=pins/spi-transfer weight=4 advanced=true
//% blockId=spi_transfer block="spi transfer %command into %response"

Просмотреть файл

@ -209,7 +209,7 @@ static void sendBtnUp(Event ev) {
void setupButton(int buttonId, int key) {
int pin = getConfig(key);
if (pin == -1)
target_panic(PANIC_NO_SUCH_CONFIG);
return;
unsigned highflags = (unsigned)pin >> 16;
int flags = BUTTON_ACTIVE_LOW_PULL_UP;

Просмотреть файл

@ -20,11 +20,17 @@ class Flash {
* Write given number of bytes within one page. Flash has to be erased first.
*/
virtual int writeBytes(uintptr_t dst, const void *src, uint32_t len) = 0;
/**
* Return the total size of flash.
*/
virtual int totalSize();
};
class ZFlash : public Flash {
public:
virtual int pageSize(uintptr_t address);
virtual int totalSize();
virtual int erasePage(uintptr_t address);
virtual int writeBytes(uintptr_t dst, const void *src, uint32_t len);
};

Просмотреть файл

@ -0,0 +1,80 @@
#include "pxt.h"
#include "Flash.h"
//#define LOG DMESG
#define LOG NOLOG
#if defined(NRF52_SERIES)
namespace codal {
#define waitForLast() while ((NRF_NVMC->READY & NVMC_READY_READY_Msk) == 0);
int ZFlash::pageSize(uintptr_t address) {
(void)address;
#if defined(FICR_INFO_CODEPAGESIZE_CODEPAGESIZE_Msk)
return NRF_FICR->INFO.CODEPAGESIZE;
#else
return NRF_FICR->CODEPAGESIZE;
#endif
}
int ZFlash::totalSize() {
#if defined(FICR_INFO_CODEPAGESIZE_CODEPAGESIZE_Msk)
return NRF_FICR->INFO.CODESIZE * pageSize(0);
#else
return NRF_FICR->CODESIZE * pageSize(0);
#endif
}
int ZFlash::erasePage(uintptr_t address) {
if (address & (pageSize(address) - 1))
target_panic(DEVICE_FLASH_ERROR);
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een;
waitForLast();
NRF_NVMC->ERASEPAGE = address;
waitForLast();
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
waitForLast();
return 0;
}
int ZFlash::writeBytes(uintptr_t dst, const void *src, uint32_t len) {
LOG("WR flash at %p len=%d", (void *)dst, len);
if ((dst & 3) || ((uintptr_t)src & 3) || (len & 3))
return -1;
for (unsigned i = 0; i < len; ++i)
if (((uint8_t *)dst)[i] != 0xff && ((uint8_t *)src)[i] != 0xff)
return -3;
volatile uint32_t *sp = (uint32_t *)src;
volatile uint32_t *dp = (uint32_t *)dst;
len >>= 2;
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
waitForLast();
while (len-- > 0) {
uint32_t v = *sp++;
if (v != 0xffffffff) {
*dp++ = v;
waitForLast();
} else {
dp++;
}
}
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
waitForLast();
LOG("WR flash OK");
return 0;
}
} // namespace codal
#endif

Просмотреть файл

@ -45,12 +45,17 @@ static void lock() {
#endif
}
int ZFlash::totalSize() {
return (8 << NVMCTRL->PARAM.bit.PSZ) * NVMCTRL->PARAM.bit.NVMP;
}
// this returns the size of "page" that can be erased ("row" in datasheet)
int ZFlash::pageSize(uintptr_t address) {
#ifdef SAMD51
if (address < 1024 * 1024)
if (address < (uintptr_t)totalSize())
return NVMCTRL_BLOCK_SIZE; // 8k
#else
if (address < 256 * 1024)
if (address < (uintptr_t)totalSize())
return 256;
#endif
target_panic(DEVICE_FLASH_ERROR);

Просмотреть файл

@ -33,6 +33,10 @@ int ZFlash::pageSize(uintptr_t address) {
return 0;
}
int ZFlash::totalSize() {
return *((uint16_t *)0x1FFF7A22) * 1024;
}
int ZFlash::erasePage(uintptr_t address) {
waitForLast();
unlock();

Просмотреть файл

@ -8,6 +8,7 @@
"Flash.h",
"STM32Flash.cpp",
"SAMDFlash.cpp",
"NRF52Flash.cpp",
"settings.cpp",
"settings.ts",
"shims.d.ts"

Просмотреть файл

@ -8,24 +8,37 @@ using namespace codal;
namespace settings {
#if defined(SAMD21)
#define SETTINGS_SIZE (2 * 1024)
#else
#define SETTINGS_SIZE (32 * 1024)
#endif
class WStorage {
public:
CODAL_FLASH flash;
FS fs;
bool isMounted;
WStorage() : flash(),
WStorage()
: flash(),
#if defined(STM32F4)
fs(flash, 0x8008000, 32 * 1024),
fs(flash, 0x8008000, SETTINGS_SIZE),
#elif defined(SAMD51)
fs(flash, 512*1024 - 32*1024, 32 * 1024),
fs(flash, 512 * 1024 - SETTINGS_SIZE, SETTINGS_SIZE),
#elif defined(SAMD21)
fs(flash, 256*1024 - 2*1024, 2 * 1024),
fs(flash, 256 * 1024 - SETTINGS_SIZE, SETTINGS_SIZE),
#elif defined(NRF52_SERIES)
#define NRF_BOOTLOADER_START *(uint32_t *)0x10001014
fs(flash,
128 * 1024 < NRF_BOOTLOADER_START && NRF_BOOTLOADER_START < (uint32_t)flash.totalSize()
? NRF_BOOTLOADER_START - SETTINGS_SIZE
: flash.totalSize() - SETTINGS_SIZE,
SETTINGS_SIZE),
#else
fs(flash),
fs(flash),
#endif
isMounted(false)
{
isMounted(false) {
fs.minGCSpacing = 10000;
}
};
@ -114,5 +127,4 @@ RefCollection *_list(String prefix) {
return res;
}
} // namespace settings