add support for NRF52 (#1067)
* 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:
Родитель
4e9abf5c77
Коммит
d411cee039
|
@ -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
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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"
|
||||
}
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче