rp2040js 0.19.4 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/clock/clock.d.ts +6 -8
- package/dist/cjs/clock/mock-clock.d.ts +2 -15
- package/dist/cjs/clock/mock-clock.js +4 -46
- package/dist/cjs/clock/simulation-clock.d.ts +26 -0
- package/dist/cjs/clock/simulation-clock.js +97 -0
- package/dist/cjs/cortex-m0-core.d.ts +1 -1
- package/dist/cjs/cortex-m0-core.js +39 -37
- package/dist/cjs/gdb/gdb-connection.d.ts +1 -1
- package/dist/cjs/gdb/gdb-connection.js +2 -2
- package/dist/cjs/gdb/gdb-server.d.ts +3 -3
- package/dist/cjs/gdb/gdb-server.js +12 -11
- package/dist/cjs/gdb/gdb-target.d.ts +7 -0
- package/dist/cjs/gdb/gdb-target.js +2 -0
- package/dist/cjs/gdb/gdb-tcp-server.d.ts +2 -2
- package/dist/cjs/gdb/gdb-tcp-server.js +2 -2
- package/dist/cjs/index.d.ts +4 -3
- package/dist/cjs/index.js +7 -5
- package/dist/cjs/peripherals/adc.d.ts +7 -2
- package/dist/cjs/peripherals/adc.js +12 -8
- package/dist/cjs/peripherals/dma.d.ts +1 -1
- package/dist/cjs/peripherals/dma.js +6 -15
- package/dist/cjs/peripherals/rtc.d.ts +1 -1
- package/dist/cjs/peripherals/rtc.js +3 -3
- package/dist/cjs/peripherals/timer.js +12 -17
- package/dist/cjs/peripherals/usb.d.ts +4 -0
- package/dist/cjs/peripherals/usb.js +56 -50
- package/dist/cjs/rp2040.d.ts +0 -5
- package/dist/cjs/rp2040.js +2 -27
- package/dist/cjs/simulator.d.ts +13 -0
- package/dist/cjs/simulator.js +45 -0
- package/dist/cjs/utils/timer32.d.ts +3 -3
- package/dist/cjs/utils/timer32.js +14 -16
- package/dist/esm/clock/clock.d.ts +6 -8
- package/dist/esm/clock/mock-clock.d.ts +2 -15
- package/dist/esm/clock/mock-clock.js +3 -44
- package/dist/esm/clock/simulation-clock.d.ts +26 -0
- package/dist/esm/clock/simulation-clock.js +92 -0
- package/dist/esm/cortex-m0-core.d.ts +1 -1
- package/dist/esm/cortex-m0-core.js +39 -37
- package/dist/esm/gdb/gdb-connection.d.ts +1 -1
- package/dist/esm/gdb/gdb-connection.js +2 -2
- package/dist/esm/gdb/gdb-server.d.ts +3 -3
- package/dist/esm/gdb/gdb-server.js +12 -11
- package/dist/esm/gdb/gdb-target.d.ts +7 -0
- package/dist/esm/gdb/gdb-target.js +1 -0
- package/dist/esm/gdb/gdb-tcp-server.d.ts +2 -2
- package/dist/esm/gdb/gdb-tcp-server.js +2 -2
- package/dist/esm/index.d.ts +4 -3
- package/dist/esm/index.js +2 -1
- package/dist/esm/peripherals/adc.d.ts +7 -2
- package/dist/esm/peripherals/adc.js +12 -8
- package/dist/esm/peripherals/dma.d.ts +1 -1
- package/dist/esm/peripherals/dma.js +6 -15
- package/dist/esm/peripherals/rtc.d.ts +1 -1
- package/dist/esm/peripherals/rtc.js +3 -3
- package/dist/esm/peripherals/timer.js +12 -17
- package/dist/esm/peripherals/usb.d.ts +4 -0
- package/dist/esm/peripherals/usb.js +56 -50
- package/dist/esm/rp2040.d.ts +0 -5
- package/dist/esm/rp2040.js +2 -27
- package/dist/esm/simulator.d.ts +13 -0
- package/dist/esm/simulator.js +41 -0
- package/dist/esm/utils/timer32.d.ts +3 -3
- package/dist/esm/utils/timer32.js +14 -16
- package/package.json +1 -1
- package/dist/cjs/clock/realtime-clock.d.ts +0 -23
- package/dist/cjs/clock/realtime-clock.js +0 -73
- package/dist/esm/clock/realtime-clock.d.ts +0 -23
- package/dist/esm/clock/realtime-clock.js +0 -68
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { Socket } from 'net';
|
|
3
3
|
import { GDBServer } from './gdb-server.js';
|
|
4
|
-
import {
|
|
4
|
+
import { IGDBTarget } from './gdb-target.js';
|
|
5
5
|
export declare class GDBTCPServer extends GDBServer {
|
|
6
6
|
readonly port: number;
|
|
7
7
|
private socketServer;
|
|
8
|
-
constructor(
|
|
8
|
+
constructor(target: IGDBTarget, port?: number);
|
|
9
9
|
handleConnection(socket: Socket): void;
|
|
10
10
|
}
|
|
@@ -5,8 +5,8 @@ const net_1 = require("net");
|
|
|
5
5
|
const gdb_connection_js_1 = require("./gdb-connection.js");
|
|
6
6
|
const gdb_server_js_1 = require("./gdb-server.js");
|
|
7
7
|
class GDBTCPServer extends gdb_server_js_1.GDBServer {
|
|
8
|
-
constructor(
|
|
9
|
-
super(
|
|
8
|
+
constructor(target, port = 3333) {
|
|
9
|
+
super(target);
|
|
10
10
|
this.port = port;
|
|
11
11
|
this.socketServer = (0, net_1.createServer)();
|
|
12
12
|
this.socketServer.listen(port);
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
export { GDBConnection } from './gdb/gdb-connection.js';
|
|
2
2
|
export { GDBServer } from './gdb/gdb-server.js';
|
|
3
3
|
export { GPIOPin, GPIOPinState } from './gpio-pin.js';
|
|
4
|
+
export { I2CMode, I2CSpeed, RPI2C } from './peripherals/i2c.js';
|
|
4
5
|
export { BasePeripheral, type Peripheral } from './peripherals/peripheral.js';
|
|
5
|
-
export { RPI2C, I2CSpeed, I2CMode } from './peripherals/i2c.js';
|
|
6
6
|
export { RPUSBController } from './peripherals/usb.js';
|
|
7
7
|
export { RP2040 } from './rp2040.js';
|
|
8
|
+
export { Simulator } from './simulator.js';
|
|
8
9
|
export { USBCDC } from './usb/cdc.js';
|
|
9
|
-
export { DataDirection, DescriptorType,
|
|
10
|
+
export { DataDirection, DescriptorType, SetupRecipient, SetupRequest, SetupType, type ISetupPacketParams, } from './usb/interfaces.js';
|
|
10
11
|
export { createSetupPacket, getDescriptorPacket, setDeviceAddressPacket, setDeviceConfigurationPacket, } from './usb/setup.js';
|
|
11
|
-
export { ConsoleLogger, type Logger
|
|
12
|
+
export { ConsoleLogger, LogLevel, type Logger } from './utils/logging.js';
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LogLevel = exports.ConsoleLogger = exports.setDeviceConfigurationPacket = exports.setDeviceAddressPacket = exports.getDescriptorPacket = exports.createSetupPacket = exports.SetupType = exports.SetupRequest = exports.SetupRecipient = exports.DescriptorType = exports.DataDirection = exports.USBCDC = exports.RP2040 = exports.RPUSBController = exports.
|
|
3
|
+
exports.LogLevel = exports.ConsoleLogger = exports.setDeviceConfigurationPacket = exports.setDeviceAddressPacket = exports.getDescriptorPacket = exports.createSetupPacket = exports.SetupType = exports.SetupRequest = exports.SetupRecipient = exports.DescriptorType = exports.DataDirection = exports.USBCDC = exports.Simulator = exports.RP2040 = exports.RPUSBController = exports.BasePeripheral = exports.RPI2C = exports.I2CSpeed = exports.I2CMode = exports.GPIOPinState = exports.GPIOPin = exports.GDBServer = exports.GDBConnection = void 0;
|
|
4
4
|
var gdb_connection_js_1 = require("./gdb/gdb-connection.js");
|
|
5
5
|
Object.defineProperty(exports, "GDBConnection", { enumerable: true, get: function () { return gdb_connection_js_1.GDBConnection; } });
|
|
6
6
|
var gdb_server_js_1 = require("./gdb/gdb-server.js");
|
|
@@ -8,16 +8,18 @@ Object.defineProperty(exports, "GDBServer", { enumerable: true, get: function ()
|
|
|
8
8
|
var gpio_pin_js_1 = require("./gpio-pin.js");
|
|
9
9
|
Object.defineProperty(exports, "GPIOPin", { enumerable: true, get: function () { return gpio_pin_js_1.GPIOPin; } });
|
|
10
10
|
Object.defineProperty(exports, "GPIOPinState", { enumerable: true, get: function () { return gpio_pin_js_1.GPIOPinState; } });
|
|
11
|
-
var peripheral_js_1 = require("./peripherals/peripheral.js");
|
|
12
|
-
Object.defineProperty(exports, "BasePeripheral", { enumerable: true, get: function () { return peripheral_js_1.BasePeripheral; } });
|
|
13
11
|
var i2c_js_1 = require("./peripherals/i2c.js");
|
|
14
|
-
Object.defineProperty(exports, "RPI2C", { enumerable: true, get: function () { return i2c_js_1.RPI2C; } });
|
|
15
|
-
Object.defineProperty(exports, "I2CSpeed", { enumerable: true, get: function () { return i2c_js_1.I2CSpeed; } });
|
|
16
12
|
Object.defineProperty(exports, "I2CMode", { enumerable: true, get: function () { return i2c_js_1.I2CMode; } });
|
|
13
|
+
Object.defineProperty(exports, "I2CSpeed", { enumerable: true, get: function () { return i2c_js_1.I2CSpeed; } });
|
|
14
|
+
Object.defineProperty(exports, "RPI2C", { enumerable: true, get: function () { return i2c_js_1.RPI2C; } });
|
|
15
|
+
var peripheral_js_1 = require("./peripherals/peripheral.js");
|
|
16
|
+
Object.defineProperty(exports, "BasePeripheral", { enumerable: true, get: function () { return peripheral_js_1.BasePeripheral; } });
|
|
17
17
|
var usb_js_1 = require("./peripherals/usb.js");
|
|
18
18
|
Object.defineProperty(exports, "RPUSBController", { enumerable: true, get: function () { return usb_js_1.RPUSBController; } });
|
|
19
19
|
var rp2040_js_1 = require("./rp2040.js");
|
|
20
20
|
Object.defineProperty(exports, "RP2040", { enumerable: true, get: function () { return rp2040_js_1.RP2040; } });
|
|
21
|
+
var simulator_js_1 = require("./simulator.js");
|
|
22
|
+
Object.defineProperty(exports, "Simulator", { enumerable: true, get: function () { return simulator_js_1.Simulator; } });
|
|
21
23
|
var cdc_js_1 = require("./usb/cdc.js");
|
|
22
24
|
Object.defineProperty(exports, "USBCDC", { enumerable: true, get: function () { return cdc_js_1.USBCDC; } });
|
|
23
25
|
var interfaces_js_1 = require("./usb/interfaces.js");
|
|
@@ -19,10 +19,10 @@ export declare class RPADC extends BasePeripheral implements Peripheral {
|
|
|
19
19
|
* Invoked whenever the emulated code performs an ADC read.
|
|
20
20
|
*
|
|
21
21
|
* The default implementation reads the result from the `channelValues` array, and then calls
|
|
22
|
-
* completeADCRead() after `sampleTime`
|
|
22
|
+
* completeADCRead() after `sampleTime` microseconds.
|
|
23
23
|
*
|
|
24
24
|
* If you override the default implementation, make sure to call `completeADCRead()` after
|
|
25
|
-
* `sampleTime`
|
|
25
|
+
* `sampleTime` microseconds (or else the ADC read will never complete).
|
|
26
26
|
*/
|
|
27
27
|
onADCRead: (channel: number) => void;
|
|
28
28
|
readonly fifo: FIFO;
|
|
@@ -35,6 +35,11 @@ export declare class RPADC extends BasePeripheral implements Peripheral {
|
|
|
35
35
|
result: number;
|
|
36
36
|
busy: boolean;
|
|
37
37
|
err: boolean;
|
|
38
|
+
currentChannel: number;
|
|
39
|
+
/** Used to simulate ADC sample time */
|
|
40
|
+
sampleAlarm: import("../clock/clock.js").IAlarm;
|
|
41
|
+
/** For scheduling multi-shot ADC capture */
|
|
42
|
+
multiShotAlarm: import("../clock/clock.js").IAlarm;
|
|
38
43
|
get temperatueEnable(): number;
|
|
39
44
|
get enabled(): number;
|
|
40
45
|
get divider(): number;
|
|
@@ -100,14 +100,15 @@ class RPADC extends peripheral_js_1.BasePeripheral {
|
|
|
100
100
|
* Invoked whenever the emulated code performs an ADC read.
|
|
101
101
|
*
|
|
102
102
|
* The default implementation reads the result from the `channelValues` array, and then calls
|
|
103
|
-
* completeADCRead() after `sampleTime`
|
|
103
|
+
* completeADCRead() after `sampleTime` microseconds.
|
|
104
104
|
*
|
|
105
105
|
* If you override the default implementation, make sure to call `completeADCRead()` after
|
|
106
|
-
* `sampleTime`
|
|
106
|
+
* `sampleTime` microseconds (or else the ADC read will never complete).
|
|
107
107
|
*/
|
|
108
108
|
this.onADCRead = (channel) => {
|
|
109
109
|
// Default implementation
|
|
110
|
-
this.
|
|
110
|
+
this.currentChannel = channel;
|
|
111
|
+
this.sampleAlarm.schedule(this.sampleTime * 1000);
|
|
111
112
|
};
|
|
112
113
|
this.fifo = new fifo_js_1.FIFO(4);
|
|
113
114
|
this.dreq = dma_js_1.DREQChannel.DREQ_ADC;
|
|
@@ -121,6 +122,13 @@ class RPADC extends peripheral_js_1.BasePeripheral {
|
|
|
121
122
|
// Status
|
|
122
123
|
this.busy = false;
|
|
123
124
|
this.err = false;
|
|
125
|
+
this.currentChannel = 0;
|
|
126
|
+
this.sampleAlarm = this.rp2040.clock.createAlarm(() => this.completeADCRead(this.channelValues[this.currentChannel], false));
|
|
127
|
+
this.multiShotAlarm = this.rp2040.clock.createAlarm(() => {
|
|
128
|
+
if (this.cs & CS_START_MANY) {
|
|
129
|
+
this.startADCRead();
|
|
130
|
+
}
|
|
131
|
+
});
|
|
124
132
|
}
|
|
125
133
|
checkInterrupts() {
|
|
126
134
|
this.rp2040.setInterrupt(irq_js_1.IRQ.ADC_FIFO, !!this.intStatus);
|
|
@@ -183,11 +191,7 @@ class RPADC extends peripheral_js_1.BasePeripheral {
|
|
|
183
191
|
if (this.divider > sampleTicks) {
|
|
184
192
|
// clock runs at 48MHz, subtract 2uS
|
|
185
193
|
const micros = (this.divider - sampleTicks) / clockMHZ;
|
|
186
|
-
this.
|
|
187
|
-
if (this.cs & CS_START_MANY) {
|
|
188
|
-
this.startADCRead();
|
|
189
|
-
}
|
|
190
|
-
});
|
|
194
|
+
this.multiShotAlarm.schedule(micros * 1000);
|
|
191
195
|
}
|
|
192
196
|
else {
|
|
193
197
|
this.startADCRead();
|
|
@@ -133,7 +133,6 @@ class RPDMAChannel {
|
|
|
133
133
|
this.chainTo = 0;
|
|
134
134
|
this.ringMask = 0;
|
|
135
135
|
this.transferFn = () => 0;
|
|
136
|
-
this.transferTimer = null;
|
|
137
136
|
this.transfer8 = () => {
|
|
138
137
|
const { rp2040 } = this;
|
|
139
138
|
rp2040.writeUint8(this.writeAddr, rp2040.readUint8(this.readAddr));
|
|
@@ -162,7 +161,6 @@ class RPDMAChannel {
|
|
|
162
161
|
this.transfer = () => {
|
|
163
162
|
var _a;
|
|
164
163
|
const { ctrl, dataSize, ringMask } = this;
|
|
165
|
-
this.transferTimer = null;
|
|
166
164
|
this.transferFn();
|
|
167
165
|
if (ctrl & INCR_READ) {
|
|
168
166
|
if (ringMask && !(ctrl & RING_SEL)) {
|
|
@@ -195,6 +193,7 @@ class RPDMAChannel {
|
|
|
195
193
|
}
|
|
196
194
|
}
|
|
197
195
|
};
|
|
196
|
+
this.transferAlarm = rp2040.clock.createAlarm(this.transfer);
|
|
198
197
|
this.reset();
|
|
199
198
|
}
|
|
200
199
|
start() {
|
|
@@ -214,26 +213,19 @@ class RPDMAChannel {
|
|
|
214
213
|
return this.ctrl & EN && this.ctrl & BUSY;
|
|
215
214
|
}
|
|
216
215
|
scheduleTransfer() {
|
|
217
|
-
if (this.transferTimer) {
|
|
218
|
-
// Already scheduled; do nothing.
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
216
|
if (this.dma.dreq[this.treqValue] || this.treqValue === TREQ.Permanent) {
|
|
222
|
-
this.
|
|
217
|
+
this.transferAlarm.schedule(0);
|
|
223
218
|
}
|
|
224
219
|
else {
|
|
225
220
|
const delay = this.dma.getTimer(this.treqValue);
|
|
226
221
|
if (delay) {
|
|
227
|
-
this.
|
|
222
|
+
this.transferAlarm.schedule(delay * 1000);
|
|
228
223
|
}
|
|
229
224
|
}
|
|
230
225
|
}
|
|
231
226
|
abort() {
|
|
232
227
|
this.ctrl &= ~BUSY;
|
|
233
|
-
|
|
234
|
-
this.rp2040.clock.deleteTimer(this.transferTimer);
|
|
235
|
-
this.transferTimer = null;
|
|
236
|
-
}
|
|
228
|
+
this.transferAlarm.cancel();
|
|
237
229
|
}
|
|
238
230
|
readUint32(offset) {
|
|
239
231
|
switch (offset) {
|
|
@@ -311,9 +303,8 @@ class RPDMAChannel {
|
|
|
311
303
|
if (this.ctrl & EN && this.ctrl & BUSY) {
|
|
312
304
|
this.scheduleTransfer();
|
|
313
305
|
}
|
|
314
|
-
if (!(this.ctrl & EN)
|
|
315
|
-
this.
|
|
316
|
-
this.transferTimer = null;
|
|
306
|
+
if (!(this.ctrl & EN)) {
|
|
307
|
+
this.transferAlarm.cancel();
|
|
317
308
|
}
|
|
318
309
|
break;
|
|
319
310
|
}
|
|
@@ -4,7 +4,7 @@ export declare class RP2040RTC extends BasePeripheral implements Peripheral {
|
|
|
4
4
|
setup1: number;
|
|
5
5
|
ctrl: number;
|
|
6
6
|
baseline: Date;
|
|
7
|
-
|
|
7
|
+
baselineNanos: number;
|
|
8
8
|
readUint32(offset: number): number;
|
|
9
9
|
writeUint32(offset: number, value: number): void;
|
|
10
10
|
}
|
|
@@ -46,10 +46,10 @@ class RP2040RTC extends peripheral_js_1.BasePeripheral {
|
|
|
46
46
|
this.setup1 = 0;
|
|
47
47
|
this.ctrl = 0;
|
|
48
48
|
this.baseline = new Date(2021, 0, 1);
|
|
49
|
-
this.
|
|
49
|
+
this.baselineNanos = 0;
|
|
50
50
|
}
|
|
51
51
|
readUint32(offset) {
|
|
52
|
-
const date = new Date(this.baseline.getTime() + (this.rp2040.clock.
|
|
52
|
+
const date = new Date(this.baseline.getTime() + (this.rp2040.clock.nanos - this.baselineNanos) / 1000000);
|
|
53
53
|
switch (offset) {
|
|
54
54
|
case RTC_SETUP0:
|
|
55
55
|
return this.setup0;
|
|
@@ -99,7 +99,7 @@ class RP2040RTC extends peripheral_js_1.BasePeripheral {
|
|
|
99
99
|
const min = (this.setup1 >> SETUP_1_MIN_SHIFT) & SETUP_1_MIN_MASK;
|
|
100
100
|
const sec = (this.setup1 >> SETUP_1_SEC_SHIFT) & SETUP_1_SEC_MASK;
|
|
101
101
|
this.baseline = new Date(year, month - 1, day, hour, min, sec);
|
|
102
|
-
this.
|
|
102
|
+
this.baselineNanos = this.rp2040.clock.nanos;
|
|
103
103
|
this.ctrl &= ~RTC_LOAD_BITS;
|
|
104
104
|
}
|
|
105
105
|
}
|
|
@@ -23,35 +23,34 @@ const ALARM_2 = 1 << 2;
|
|
|
23
23
|
const ALARM_3 = 1 << 3;
|
|
24
24
|
const timerInterrupts = [irq_js_1.IRQ.TIMER_0, irq_js_1.IRQ.TIMER_1, irq_js_1.IRQ.TIMER_2, irq_js_1.IRQ.TIMER_3];
|
|
25
25
|
class RPTimerAlarm {
|
|
26
|
-
constructor(
|
|
27
|
-
this.name = name;
|
|
26
|
+
constructor(bitValue, clockAlarm) {
|
|
28
27
|
this.bitValue = bitValue;
|
|
28
|
+
this.clockAlarm = clockAlarm;
|
|
29
29
|
this.armed = false;
|
|
30
30
|
this.targetMicros = 0;
|
|
31
|
-
this.timer = null;
|
|
32
31
|
}
|
|
33
32
|
}
|
|
34
33
|
class RPTimer extends peripheral_js_1.BasePeripheral {
|
|
35
34
|
constructor(rp2040, name) {
|
|
36
35
|
super(rp2040, name);
|
|
37
36
|
this.latchedTimeHigh = 0;
|
|
38
|
-
this.alarms = [
|
|
39
|
-
new RPTimerAlarm('Alarm 0', ALARM_0),
|
|
40
|
-
new RPTimerAlarm('Alarm 1', ALARM_1),
|
|
41
|
-
new RPTimerAlarm('Alarm 2', ALARM_2),
|
|
42
|
-
new RPTimerAlarm('Alarm 3', ALARM_3),
|
|
43
|
-
];
|
|
44
37
|
this.intRaw = 0;
|
|
45
38
|
this.intEnable = 0;
|
|
46
39
|
this.intForce = 0;
|
|
47
40
|
this.paused = false;
|
|
48
41
|
this.clock = rp2040.clock;
|
|
42
|
+
this.alarms = [
|
|
43
|
+
new RPTimerAlarm(ALARM_0, this.clock.createAlarm(() => this.fireAlarm(0))),
|
|
44
|
+
new RPTimerAlarm(ALARM_1, this.clock.createAlarm(() => this.fireAlarm(1))),
|
|
45
|
+
new RPTimerAlarm(ALARM_2, this.clock.createAlarm(() => this.fireAlarm(2))),
|
|
46
|
+
new RPTimerAlarm(ALARM_3, this.clock.createAlarm(() => this.fireAlarm(3))),
|
|
47
|
+
];
|
|
49
48
|
}
|
|
50
49
|
get intStatus() {
|
|
51
50
|
return (this.intRaw & this.intEnable) | this.intForce;
|
|
52
51
|
}
|
|
53
52
|
readUint32(offset) {
|
|
54
|
-
const time = this.clock.
|
|
53
|
+
const time = this.clock.nanos / 1000;
|
|
55
54
|
switch (offset) {
|
|
56
55
|
case TIMEHR:
|
|
57
56
|
return this.latchedTimeHigh;
|
|
@@ -96,11 +95,10 @@ class RPTimer extends peripheral_js_1.BasePeripheral {
|
|
|
96
95
|
case ALARM3: {
|
|
97
96
|
const alarmIndex = (offset - ALARM0) / 4;
|
|
98
97
|
const alarm = this.alarms[alarmIndex];
|
|
99
|
-
const
|
|
100
|
-
this.disarmAlarm(alarm);
|
|
98
|
+
const deltaMicros = (value - this.clock.nanos / 1000) >>> 0;
|
|
101
99
|
alarm.armed = true;
|
|
102
100
|
alarm.targetMicros = value;
|
|
103
|
-
alarm.
|
|
101
|
+
alarm.clockAlarm.schedule(deltaMicros * 1000);
|
|
104
102
|
break;
|
|
105
103
|
}
|
|
106
104
|
case ARMED:
|
|
@@ -146,10 +144,7 @@ class RPTimer extends peripheral_js_1.BasePeripheral {
|
|
|
146
144
|
}
|
|
147
145
|
}
|
|
148
146
|
disarmAlarm(alarm) {
|
|
149
|
-
|
|
150
|
-
this.clock.deleteTimer(alarm.timer);
|
|
151
|
-
alarm.timer = null;
|
|
152
|
-
}
|
|
147
|
+
alarm.clockAlarm.cancel();
|
|
153
148
|
alarm.armed = false;
|
|
154
149
|
}
|
|
155
150
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RP2040 } from '../rp2040.js';
|
|
1
2
|
import { BasePeripheral } from './peripheral.js';
|
|
2
3
|
export declare class RPUSBController extends BasePeripheral {
|
|
3
4
|
private mainCtrl;
|
|
@@ -6,6 +7,8 @@ export declare class RPUSBController extends BasePeripheral {
|
|
|
6
7
|
private intForce;
|
|
7
8
|
private sieStatus;
|
|
8
9
|
private buffStatus;
|
|
10
|
+
private readonly endpointReadAlarms;
|
|
11
|
+
private readonly endpointWriteAlarms;
|
|
9
12
|
onUSBEnabled?: () => void;
|
|
10
13
|
onResetReceived?: () => void;
|
|
11
14
|
onEndpointWrite?: (endpoint: number, buffer: Uint8Array) => void;
|
|
@@ -13,6 +16,7 @@ export declare class RPUSBController extends BasePeripheral {
|
|
|
13
16
|
readDelayMicroseconds: number;
|
|
14
17
|
writeDelayMicroseconds: number;
|
|
15
18
|
get intStatus(): number;
|
|
19
|
+
constructor(rp2040: RP2040, name: string);
|
|
16
20
|
readUint32(offset: number): number;
|
|
17
21
|
writeUint32(offset: number, value: number): void;
|
|
18
22
|
private readEndpointControlReg;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.RPUSBController = void 0;
|
|
4
4
|
const irq_js_1 = require("../irq.js");
|
|
5
5
|
const peripheral_js_1 = require("./peripheral.js");
|
|
6
|
+
const ENDPOINT_COUNT = 16;
|
|
6
7
|
// USB DPSRAM Registers
|
|
7
8
|
const EP1_IN_CONTROL = 0x8;
|
|
8
9
|
const EP0_IN_BUFFER_CONTROL = 0x80;
|
|
@@ -80,9 +81,22 @@ const SIE_WRITECLEAR_MASK = SIE_DATA_SEQ_ERROR |
|
|
|
80
81
|
SIE_TRANS_COMPLETE |
|
|
81
82
|
SIE_SETUP_REC |
|
|
82
83
|
SIE_RESUME;
|
|
84
|
+
class USBEndpointAlarm {
|
|
85
|
+
constructor(alarm) {
|
|
86
|
+
this.alarm = alarm;
|
|
87
|
+
this.buffers = [];
|
|
88
|
+
}
|
|
89
|
+
schedule(buffer, delayNanos) {
|
|
90
|
+
this.buffers.push(buffer);
|
|
91
|
+
this.alarm.schedule(delayNanos);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
83
94
|
class RPUSBController extends peripheral_js_1.BasePeripheral {
|
|
84
|
-
|
|
85
|
-
|
|
95
|
+
get intStatus() {
|
|
96
|
+
return (this.intRaw & this.intEnable) | this.intForce;
|
|
97
|
+
}
|
|
98
|
+
constructor(rp2040, name) {
|
|
99
|
+
super(rp2040, name);
|
|
86
100
|
this.mainCtrl = 0;
|
|
87
101
|
this.intRaw = 0;
|
|
88
102
|
this.intEnable = 0;
|
|
@@ -90,10 +104,25 @@ class RPUSBController extends peripheral_js_1.BasePeripheral {
|
|
|
90
104
|
this.sieStatus = 0;
|
|
91
105
|
this.buffStatus = 0;
|
|
92
106
|
this.readDelayMicroseconds = 1;
|
|
93
|
-
this.writeDelayMicroseconds =
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
107
|
+
this.writeDelayMicroseconds = 10; // Determined empirically
|
|
108
|
+
const clock = rp2040.clock;
|
|
109
|
+
this.endpointReadAlarms = [];
|
|
110
|
+
this.endpointWriteAlarms = [];
|
|
111
|
+
for (let i = 0; i < ENDPOINT_COUNT; ++i) {
|
|
112
|
+
this.endpointReadAlarms.push(new USBEndpointAlarm(clock.createAlarm(() => {
|
|
113
|
+
const buffer = this.endpointReadAlarms[i].buffers.shift();
|
|
114
|
+
if (buffer) {
|
|
115
|
+
this.finishRead(i, buffer);
|
|
116
|
+
}
|
|
117
|
+
})));
|
|
118
|
+
this.endpointWriteAlarms.push(new USBEndpointAlarm(clock.createAlarm(() => {
|
|
119
|
+
var _a;
|
|
120
|
+
for (const buffer of this.endpointWriteAlarms[i].buffers) {
|
|
121
|
+
(_a = this.onEndpointWrite) === null || _a === void 0 ? void 0 : _a.call(this, i, buffer);
|
|
122
|
+
}
|
|
123
|
+
this.endpointWriteAlarms[i].buffers = [];
|
|
124
|
+
})));
|
|
125
|
+
}
|
|
97
126
|
}
|
|
98
127
|
readUint32(offset) {
|
|
99
128
|
switch (offset) {
|
|
@@ -167,7 +196,7 @@ class RPUSBController extends peripheral_js_1.BasePeripheral {
|
|
|
167
196
|
return this.readEndpointControlReg(endpoint, out) & 0xffc0;
|
|
168
197
|
}
|
|
169
198
|
DPRAMUpdated(offset, value) {
|
|
170
|
-
var _a, _b
|
|
199
|
+
var _a, _b;
|
|
171
200
|
if (value & USB_BUF_CTRL_AVAILABLE &&
|
|
172
201
|
offset >= EP0_IN_BUFFER_CONTROL &&
|
|
173
202
|
offset <= EP15_OUT_BUFFER_CONTROL) {
|
|
@@ -180,31 +209,6 @@ class RPUSBController extends peripheral_js_1.BasePeripheral {
|
|
|
180
209
|
doubleBuffer = !!(control & USB_CTRL_DOUBLE_BUF);
|
|
181
210
|
interrupt = !!(control & USB_CTRL_INTERRUPT_PER_TRANSFER);
|
|
182
211
|
}
|
|
183
|
-
const bufferLength = value & USB_BUF_CTRL_LEN_MASK;
|
|
184
|
-
const bufferOffset = this.getEndpointBufferOffset(endpoint, bufferOut);
|
|
185
|
-
this.debug(`Start USB transfer, endPoint=${endpoint}, direction=${bufferOut ? 'out' : 'in'} buffer=${bufferOffset.toString(16)} length=${bufferLength}`);
|
|
186
|
-
value &= ~USB_BUF_CTRL_AVAILABLE;
|
|
187
|
-
this.rp2040.usbDPRAMView.setUint32(offset, value, true);
|
|
188
|
-
if (bufferOut) {
|
|
189
|
-
(_a = this.onEndpointRead) === null || _a === void 0 ? void 0 : _a.call(this, endpoint, bufferLength);
|
|
190
|
-
}
|
|
191
|
-
else {
|
|
192
|
-
value &= ~USB_BUF_CTRL_FULL;
|
|
193
|
-
this.rp2040.usbDPRAMView.setUint32(offset, value, true);
|
|
194
|
-
const buffer = this.rp2040.usbDPRAM.slice(bufferOffset, bufferOffset + bufferLength);
|
|
195
|
-
if (interrupt || !doubleBuffer) {
|
|
196
|
-
this.indicateBufferReady(endpoint, false);
|
|
197
|
-
}
|
|
198
|
-
if (this.writeDelayMicroseconds) {
|
|
199
|
-
this.rp2040.clock.createTimer(this.writeDelayMicroseconds, () => {
|
|
200
|
-
var _a;
|
|
201
|
-
(_a = this.onEndpointWrite) === null || _a === void 0 ? void 0 : _a.call(this, endpoint, buffer);
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
(_b = this.onEndpointWrite) === null || _b === void 0 ? void 0 : _b.call(this, endpoint, buffer);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
212
|
if (doubleBuffer && (value >> USB_BUF1_SHIFT) & USB_BUF_CTRL_AVAILABLE) {
|
|
209
213
|
const bufferLength = (value >> USB_BUF1_SHIFT) & USB_BUF_CTRL_LEN_MASK;
|
|
210
214
|
const bufferOffset = this.getEndpointBufferOffset(endpoint, bufferOut) + USB_BUF1_OFFSET;
|
|
@@ -212,35 +216,37 @@ class RPUSBController extends peripheral_js_1.BasePeripheral {
|
|
|
212
216
|
value &= ~(USB_BUF_CTRL_AVAILABLE << USB_BUF1_SHIFT);
|
|
213
217
|
this.rp2040.usbDPRAMView.setUint32(offset, value, true);
|
|
214
218
|
if (bufferOut) {
|
|
215
|
-
(
|
|
219
|
+
(_a = this.onEndpointRead) === null || _a === void 0 ? void 0 : _a.call(this, endpoint, bufferLength);
|
|
216
220
|
}
|
|
217
221
|
else {
|
|
218
222
|
value &= ~(USB_BUF_CTRL_FULL << USB_BUF1_SHIFT);
|
|
219
223
|
this.rp2040.usbDPRAMView.setUint32(offset, value, true);
|
|
220
224
|
const buffer = this.rp2040.usbDPRAM.slice(bufferOffset, bufferOffset + bufferLength);
|
|
221
225
|
this.indicateBufferReady(endpoint, false);
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
226
|
+
this.endpointWriteAlarms[endpoint].schedule(buffer, this.writeDelayMicroseconds * 1000);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const bufferLength = value & USB_BUF_CTRL_LEN_MASK;
|
|
230
|
+
const bufferOffset = this.getEndpointBufferOffset(endpoint, bufferOut);
|
|
231
|
+
this.debug(`Start USB transfer, endPoint=${endpoint}, direction=${bufferOut ? 'out' : 'in'} buffer=${bufferOffset.toString(16)} length=${bufferLength}`);
|
|
232
|
+
value &= ~USB_BUF_CTRL_AVAILABLE;
|
|
233
|
+
this.rp2040.usbDPRAMView.setUint32(offset, value, true);
|
|
234
|
+
if (bufferOut) {
|
|
235
|
+
(_b = this.onEndpointRead) === null || _b === void 0 ? void 0 : _b.call(this, endpoint, bufferLength);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
value &= ~USB_BUF_CTRL_FULL;
|
|
239
|
+
this.rp2040.usbDPRAMView.setUint32(offset, value, true);
|
|
240
|
+
const buffer = this.rp2040.usbDPRAM.slice(bufferOffset, bufferOffset + bufferLength);
|
|
241
|
+
if (interrupt || !doubleBuffer) {
|
|
242
|
+
this.indicateBufferReady(endpoint, false);
|
|
231
243
|
}
|
|
244
|
+
this.endpointWriteAlarms[endpoint].schedule(buffer, this.writeDelayMicroseconds * 1000);
|
|
232
245
|
}
|
|
233
246
|
}
|
|
234
247
|
}
|
|
235
248
|
endpointReadDone(endpoint, buffer, delay = this.readDelayMicroseconds) {
|
|
236
|
-
|
|
237
|
-
this.rp2040.clock.createTimer(delay, () => {
|
|
238
|
-
this.finishRead(endpoint, buffer);
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
else {
|
|
242
|
-
this.finishRead(endpoint, buffer);
|
|
243
|
-
}
|
|
249
|
+
this.endpointReadAlarms[endpoint].schedule(buffer, delay * 1000);
|
|
244
250
|
}
|
|
245
251
|
finishRead(endpoint, buffer) {
|
|
246
252
|
const bufferOffset = this.getEndpointBufferOffset(endpoint, true);
|
package/dist/cjs/rp2040.d.ts
CHANGED
|
@@ -44,9 +44,7 @@ export declare class RP2040 {
|
|
|
44
44
|
readonly pio: RPPIO[];
|
|
45
45
|
readonly usbCtrl: RPUSBController;
|
|
46
46
|
readonly spi: RPSPI[];
|
|
47
|
-
private stopped;
|
|
48
47
|
logger: Logger;
|
|
49
|
-
private executeTimer;
|
|
50
48
|
readonly peripherals: {
|
|
51
49
|
[index: number]: Peripheral;
|
|
52
50
|
};
|
|
@@ -66,7 +64,4 @@ export declare class RP2040 {
|
|
|
66
64
|
setInterrupt(irq: number, value: boolean): void;
|
|
67
65
|
updateIOInterrupt(): void;
|
|
68
66
|
step(): void;
|
|
69
|
-
execute(): void;
|
|
70
|
-
stop(): void;
|
|
71
|
-
get executing(): boolean;
|
|
72
67
|
}
|
package/dist/cjs/rp2040.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RP2040 = exports.SIO_START_ADDRESS = exports.DPRAM_START_ADDRESS = exports.APB_START_ADDRESS = exports.RAM_START_ADDRESS = exports.FLASH_END_ADDRESS = exports.FLASH_START_ADDRESS = void 0;
|
|
4
|
-
const
|
|
4
|
+
const simulation_clock_js_1 = require("./clock/simulation-clock.js");
|
|
5
5
|
const cortex_m0_core_js_1 = require("./cortex-m0-core.js");
|
|
6
6
|
const gpio_pin_js_1 = require("./gpio-pin.js");
|
|
7
7
|
const irq_js_1 = require("./irq.js");
|
|
@@ -40,7 +40,7 @@ const KB = 1024;
|
|
|
40
40
|
const MB = 1024 * KB;
|
|
41
41
|
const MHz = 1000000;
|
|
42
42
|
class RP2040 {
|
|
43
|
-
constructor(clock = new
|
|
43
|
+
constructor(clock = new simulation_clock_js_1.SimulationClock()) {
|
|
44
44
|
this.clock = clock;
|
|
45
45
|
this.bootrom = new Uint32Array(4 * KB);
|
|
46
46
|
this.sram = new Uint8Array(264 * KB);
|
|
@@ -125,9 +125,7 @@ class RP2040 {
|
|
|
125
125
|
tx: dma_js_1.DREQChannel.DREQ_SPI1_TX,
|
|
126
126
|
}),
|
|
127
127
|
];
|
|
128
|
-
this.stopped = true;
|
|
129
128
|
this.logger = new logging_js_1.ConsoleLogger(logging_js_1.LogLevel.Debug, true);
|
|
130
|
-
this.executeTimer = null;
|
|
131
129
|
this.peripherals = {
|
|
132
130
|
0x18000: new ssi_js_1.RPSSI(this, 'SSI'),
|
|
133
131
|
0x40000: new sysinfo_js_1.RP2040SysInfo(this, 'SYSINFO_BASE'),
|
|
@@ -167,7 +165,6 @@ class RP2040 {
|
|
|
167
165
|
this.onBreak = (code) => {
|
|
168
166
|
// TODO: raise HardFault exception
|
|
169
167
|
// console.error('Breakpoint!', code);
|
|
170
|
-
this.stopped = true;
|
|
171
168
|
};
|
|
172
169
|
this.reset();
|
|
173
170
|
}
|
|
@@ -342,27 +339,5 @@ class RP2040 {
|
|
|
342
339
|
step() {
|
|
343
340
|
this.core.executeInstruction();
|
|
344
341
|
}
|
|
345
|
-
execute() {
|
|
346
|
-
this.clock.resume();
|
|
347
|
-
this.executeTimer = null;
|
|
348
|
-
this.stopped = false;
|
|
349
|
-
for (let i = 0; i < 100000 && !this.stopped && !this.core.waiting; i++) {
|
|
350
|
-
this.core.executeInstruction();
|
|
351
|
-
}
|
|
352
|
-
if (!this.stopped) {
|
|
353
|
-
this.executeTimer = setTimeout(() => this.execute(), 0);
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
stop() {
|
|
357
|
-
this.stopped = true;
|
|
358
|
-
if (this.executeTimer != null) {
|
|
359
|
-
clearTimeout(this.executeTimer);
|
|
360
|
-
this.executeTimer = null;
|
|
361
|
-
}
|
|
362
|
-
this.clock.pause();
|
|
363
|
-
}
|
|
364
|
-
get executing() {
|
|
365
|
-
return !this.stopped;
|
|
366
|
-
}
|
|
367
342
|
}
|
|
368
343
|
exports.RP2040 = RP2040;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SimulationClock } from './clock/simulation-clock.js';
|
|
2
|
+
import { IGDBTarget } from './gdb/gdb-target.js';
|
|
3
|
+
import { RP2040 } from './rp2040.js';
|
|
4
|
+
export declare class Simulator implements IGDBTarget {
|
|
5
|
+
readonly clock: SimulationClock;
|
|
6
|
+
executeTimer: ReturnType<typeof setTimeout> | null;
|
|
7
|
+
rp2040: RP2040;
|
|
8
|
+
stopped: boolean;
|
|
9
|
+
constructor(clock?: SimulationClock);
|
|
10
|
+
execute(): void;
|
|
11
|
+
stop(): void;
|
|
12
|
+
get executing(): boolean;
|
|
13
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Simulator = void 0;
|
|
4
|
+
const simulation_clock_js_1 = require("./clock/simulation-clock.js");
|
|
5
|
+
const rp2040_js_1 = require("./rp2040.js");
|
|
6
|
+
class Simulator {
|
|
7
|
+
constructor(clock = new simulation_clock_js_1.SimulationClock()) {
|
|
8
|
+
this.clock = clock;
|
|
9
|
+
this.executeTimer = null;
|
|
10
|
+
this.stopped = true;
|
|
11
|
+
this.rp2040 = new rp2040_js_1.RP2040(clock);
|
|
12
|
+
this.rp2040.onBreak = () => this.stop();
|
|
13
|
+
}
|
|
14
|
+
execute() {
|
|
15
|
+
const { rp2040, clock } = this;
|
|
16
|
+
this.executeTimer = null;
|
|
17
|
+
this.stopped = false;
|
|
18
|
+
const cycleNanos = 1e9 / 125000000; // 125 MHz
|
|
19
|
+
for (let i = 0; i < 1000000 && !this.stopped; i++) {
|
|
20
|
+
if (rp2040.core.waiting) {
|
|
21
|
+
const { nanosToNextAlarm } = clock;
|
|
22
|
+
clock.tick(nanosToNextAlarm);
|
|
23
|
+
i += nanosToNextAlarm / cycleNanos;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
const cycles = rp2040.core.executeInstruction();
|
|
27
|
+
clock.tick(cycles * cycleNanos);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (!this.stopped) {
|
|
31
|
+
this.executeTimer = setTimeout(() => this.execute(), 0);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
stop() {
|
|
35
|
+
this.stopped = true;
|
|
36
|
+
if (this.executeTimer != null) {
|
|
37
|
+
clearTimeout(this.executeTimer);
|
|
38
|
+
this.executeTimer = null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
get executing() {
|
|
42
|
+
return !this.stopped;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.Simulator = Simulator;
|