rp2040js 0.19.4 → 1.0.1
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 +5 -0
- package/dist/cjs/peripherals/usb.js +62 -53
- 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 +5 -0
- package/dist/esm/peripherals/usb.js +62 -53
- 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,9 @@ 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;
|
|
12
|
+
private readonly resetAlarm;
|
|
9
13
|
onUSBEnabled?: () => void;
|
|
10
14
|
onResetReceived?: () => void;
|
|
11
15
|
onEndpointWrite?: (endpoint: number, buffer: Uint8Array) => void;
|
|
@@ -13,6 +17,7 @@ export declare class RPUSBController extends BasePeripheral {
|
|
|
13
17
|
readDelayMicroseconds: number;
|
|
14
18
|
writeDelayMicroseconds: number;
|
|
15
19
|
get intStatus(): number;
|
|
20
|
+
constructor(rp2040: RP2040, name: string);
|
|
16
21
|
readUint32(offset: number): number;
|
|
17
22
|
writeUint32(offset: number, value: number): void;
|
|
18
23
|
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,20 +81,52 @@ 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;
|
|
89
103
|
this.intForce = 0;
|
|
90
104
|
this.sieStatus = 0;
|
|
91
105
|
this.buffStatus = 0;
|
|
92
|
-
this.readDelayMicroseconds =
|
|
93
|
-
this.writeDelayMicroseconds =
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
106
|
+
this.readDelayMicroseconds = 10;
|
|
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
|
+
}
|
|
126
|
+
this.resetAlarm = clock.createAlarm(() => {
|
|
127
|
+
this.sieStatus |= SIE_BUS_RESET;
|
|
128
|
+
this.sieStatusUpdated();
|
|
129
|
+
});
|
|
97
130
|
}
|
|
98
131
|
readUint32(offset) {
|
|
99
132
|
switch (offset) {
|
|
@@ -167,7 +200,7 @@ class RPUSBController extends peripheral_js_1.BasePeripheral {
|
|
|
167
200
|
return this.readEndpointControlReg(endpoint, out) & 0xffc0;
|
|
168
201
|
}
|
|
169
202
|
DPRAMUpdated(offset, value) {
|
|
170
|
-
var _a, _b
|
|
203
|
+
var _a, _b;
|
|
171
204
|
if (value & USB_BUF_CTRL_AVAILABLE &&
|
|
172
205
|
offset >= EP0_IN_BUFFER_CONTROL &&
|
|
173
206
|
offset <= EP15_OUT_BUFFER_CONTROL) {
|
|
@@ -180,31 +213,6 @@ class RPUSBController extends peripheral_js_1.BasePeripheral {
|
|
|
180
213
|
doubleBuffer = !!(control & USB_CTRL_DOUBLE_BUF);
|
|
181
214
|
interrupt = !!(control & USB_CTRL_INTERRUPT_PER_TRANSFER);
|
|
182
215
|
}
|
|
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
216
|
if (doubleBuffer && (value >> USB_BUF1_SHIFT) & USB_BUF_CTRL_AVAILABLE) {
|
|
209
217
|
const bufferLength = (value >> USB_BUF1_SHIFT) & USB_BUF_CTRL_LEN_MASK;
|
|
210
218
|
const bufferOffset = this.getEndpointBufferOffset(endpoint, bufferOut) + USB_BUF1_OFFSET;
|
|
@@ -212,35 +220,37 @@ class RPUSBController extends peripheral_js_1.BasePeripheral {
|
|
|
212
220
|
value &= ~(USB_BUF_CTRL_AVAILABLE << USB_BUF1_SHIFT);
|
|
213
221
|
this.rp2040.usbDPRAMView.setUint32(offset, value, true);
|
|
214
222
|
if (bufferOut) {
|
|
215
|
-
(
|
|
223
|
+
(_a = this.onEndpointRead) === null || _a === void 0 ? void 0 : _a.call(this, endpoint, bufferLength);
|
|
216
224
|
}
|
|
217
225
|
else {
|
|
218
226
|
value &= ~(USB_BUF_CTRL_FULL << USB_BUF1_SHIFT);
|
|
219
227
|
this.rp2040.usbDPRAMView.setUint32(offset, value, true);
|
|
220
228
|
const buffer = this.rp2040.usbDPRAM.slice(bufferOffset, bufferOffset + bufferLength);
|
|
221
229
|
this.indicateBufferReady(endpoint, false);
|
|
222
|
-
|
|
223
|
-
this.rp2040.clock.createTimer(this.writeDelayMicroseconds, () => {
|
|
224
|
-
var _a;
|
|
225
|
-
(_a = this.onEndpointWrite) === null || _a === void 0 ? void 0 : _a.call(this, endpoint, buffer);
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
(_d = this.onEndpointWrite) === null || _d === void 0 ? void 0 : _d.call(this, endpoint, buffer);
|
|
230
|
-
}
|
|
230
|
+
this.endpointWriteAlarms[endpoint].schedule(buffer, this.writeDelayMicroseconds * 1000);
|
|
231
231
|
}
|
|
232
232
|
}
|
|
233
|
+
const bufferLength = value & USB_BUF_CTRL_LEN_MASK;
|
|
234
|
+
const bufferOffset = this.getEndpointBufferOffset(endpoint, bufferOut);
|
|
235
|
+
this.debug(`Start USB transfer, endPoint=${endpoint}, direction=${bufferOut ? 'out' : 'in'} buffer=${bufferOffset.toString(16)} length=${bufferLength}`);
|
|
236
|
+
value &= ~USB_BUF_CTRL_AVAILABLE;
|
|
237
|
+
this.rp2040.usbDPRAMView.setUint32(offset, value, true);
|
|
238
|
+
if (bufferOut) {
|
|
239
|
+
(_b = this.onEndpointRead) === null || _b === void 0 ? void 0 : _b.call(this, endpoint, bufferLength);
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
value &= ~USB_BUF_CTRL_FULL;
|
|
243
|
+
this.rp2040.usbDPRAMView.setUint32(offset, value, true);
|
|
244
|
+
const buffer = this.rp2040.usbDPRAM.slice(bufferOffset, bufferOffset + bufferLength);
|
|
245
|
+
if (interrupt || !doubleBuffer) {
|
|
246
|
+
this.indicateBufferReady(endpoint, false);
|
|
247
|
+
}
|
|
248
|
+
this.endpointWriteAlarms[endpoint].schedule(buffer, this.writeDelayMicroseconds * 1000);
|
|
249
|
+
}
|
|
233
250
|
}
|
|
234
251
|
}
|
|
235
252
|
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
|
-
}
|
|
253
|
+
this.endpointReadAlarms[endpoint].schedule(buffer, delay * 1000);
|
|
244
254
|
}
|
|
245
255
|
finishRead(endpoint, buffer) {
|
|
246
256
|
const bufferOffset = this.getEndpointBufferOffset(endpoint, true);
|
|
@@ -259,8 +269,7 @@ class RPUSBController extends peripheral_js_1.BasePeripheral {
|
|
|
259
269
|
this.rp2040.setInterrupt(irq_js_1.IRQ.USBCTRL, !!intStatus);
|
|
260
270
|
}
|
|
261
271
|
resetDevice() {
|
|
262
|
-
this.
|
|
263
|
-
this.sieStatusUpdated();
|
|
272
|
+
this.resetAlarm.schedule(10000000); // USB reset takes ~10ms
|
|
264
273
|
}
|
|
265
274
|
sendSetupPacket(setupPacket) {
|
|
266
275
|
this.rp2040.usbDPRAM.set(setupPacket);
|
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
|
+
}
|