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.
Files changed (69) hide show
  1. package/dist/cjs/clock/clock.d.ts +6 -8
  2. package/dist/cjs/clock/mock-clock.d.ts +2 -15
  3. package/dist/cjs/clock/mock-clock.js +4 -46
  4. package/dist/cjs/clock/simulation-clock.d.ts +26 -0
  5. package/dist/cjs/clock/simulation-clock.js +97 -0
  6. package/dist/cjs/cortex-m0-core.d.ts +1 -1
  7. package/dist/cjs/cortex-m0-core.js +39 -37
  8. package/dist/cjs/gdb/gdb-connection.d.ts +1 -1
  9. package/dist/cjs/gdb/gdb-connection.js +2 -2
  10. package/dist/cjs/gdb/gdb-server.d.ts +3 -3
  11. package/dist/cjs/gdb/gdb-server.js +12 -11
  12. package/dist/cjs/gdb/gdb-target.d.ts +7 -0
  13. package/dist/cjs/gdb/gdb-target.js +2 -0
  14. package/dist/cjs/gdb/gdb-tcp-server.d.ts +2 -2
  15. package/dist/cjs/gdb/gdb-tcp-server.js +2 -2
  16. package/dist/cjs/index.d.ts +4 -3
  17. package/dist/cjs/index.js +7 -5
  18. package/dist/cjs/peripherals/adc.d.ts +7 -2
  19. package/dist/cjs/peripherals/adc.js +12 -8
  20. package/dist/cjs/peripherals/dma.d.ts +1 -1
  21. package/dist/cjs/peripherals/dma.js +6 -15
  22. package/dist/cjs/peripherals/rtc.d.ts +1 -1
  23. package/dist/cjs/peripherals/rtc.js +3 -3
  24. package/dist/cjs/peripherals/timer.js +12 -17
  25. package/dist/cjs/peripherals/usb.d.ts +4 -0
  26. package/dist/cjs/peripherals/usb.js +56 -50
  27. package/dist/cjs/rp2040.d.ts +0 -5
  28. package/dist/cjs/rp2040.js +2 -27
  29. package/dist/cjs/simulator.d.ts +13 -0
  30. package/dist/cjs/simulator.js +45 -0
  31. package/dist/cjs/utils/timer32.d.ts +3 -3
  32. package/dist/cjs/utils/timer32.js +14 -16
  33. package/dist/esm/clock/clock.d.ts +6 -8
  34. package/dist/esm/clock/mock-clock.d.ts +2 -15
  35. package/dist/esm/clock/mock-clock.js +3 -44
  36. package/dist/esm/clock/simulation-clock.d.ts +26 -0
  37. package/dist/esm/clock/simulation-clock.js +92 -0
  38. package/dist/esm/cortex-m0-core.d.ts +1 -1
  39. package/dist/esm/cortex-m0-core.js +39 -37
  40. package/dist/esm/gdb/gdb-connection.d.ts +1 -1
  41. package/dist/esm/gdb/gdb-connection.js +2 -2
  42. package/dist/esm/gdb/gdb-server.d.ts +3 -3
  43. package/dist/esm/gdb/gdb-server.js +12 -11
  44. package/dist/esm/gdb/gdb-target.d.ts +7 -0
  45. package/dist/esm/gdb/gdb-target.js +1 -0
  46. package/dist/esm/gdb/gdb-tcp-server.d.ts +2 -2
  47. package/dist/esm/gdb/gdb-tcp-server.js +2 -2
  48. package/dist/esm/index.d.ts +4 -3
  49. package/dist/esm/index.js +2 -1
  50. package/dist/esm/peripherals/adc.d.ts +7 -2
  51. package/dist/esm/peripherals/adc.js +12 -8
  52. package/dist/esm/peripherals/dma.d.ts +1 -1
  53. package/dist/esm/peripherals/dma.js +6 -15
  54. package/dist/esm/peripherals/rtc.d.ts +1 -1
  55. package/dist/esm/peripherals/rtc.js +3 -3
  56. package/dist/esm/peripherals/timer.js +12 -17
  57. package/dist/esm/peripherals/usb.d.ts +4 -0
  58. package/dist/esm/peripherals/usb.js +56 -50
  59. package/dist/esm/rp2040.d.ts +0 -5
  60. package/dist/esm/rp2040.js +2 -27
  61. package/dist/esm/simulator.d.ts +13 -0
  62. package/dist/esm/simulator.js +41 -0
  63. package/dist/esm/utils/timer32.d.ts +3 -3
  64. package/dist/esm/utils/timer32.js +14 -16
  65. package/package.json +1 -1
  66. package/dist/cjs/clock/realtime-clock.d.ts +0 -23
  67. package/dist/cjs/clock/realtime-clock.js +0 -73
  68. package/dist/esm/clock/realtime-clock.d.ts +0 -23
  69. package/dist/esm/clock/realtime-clock.js +0 -68
@@ -1,4 +1,4 @@
1
- import { RealtimeClock } from './clock/realtime-clock.js';
1
+ import { SimulationClock } from './clock/simulation-clock.js';
2
2
  import { CortexM0Core } from './cortex-m0-core.js';
3
3
  import { GPIOPin } from './gpio-pin.js';
4
4
  import { IRQ } from './irq.js';
@@ -37,7 +37,7 @@ const KB = 1024;
37
37
  const MB = 1024 * KB;
38
38
  const MHz = 1000000;
39
39
  export class RP2040 {
40
- constructor(clock = new RealtimeClock()) {
40
+ constructor(clock = new SimulationClock()) {
41
41
  this.clock = clock;
42
42
  this.bootrom = new Uint32Array(4 * KB);
43
43
  this.sram = new Uint8Array(264 * KB);
@@ -122,9 +122,7 @@ export class RP2040 {
122
122
  tx: DREQChannel.DREQ_SPI1_TX,
123
123
  }),
124
124
  ];
125
- this.stopped = true;
126
125
  this.logger = new ConsoleLogger(LogLevel.Debug, true);
127
- this.executeTimer = null;
128
126
  this.peripherals = {
129
127
  0x18000: new RPSSI(this, 'SSI'),
130
128
  0x40000: new RP2040SysInfo(this, 'SYSINFO_BASE'),
@@ -164,7 +162,6 @@ export class RP2040 {
164
162
  this.onBreak = (code) => {
165
163
  // TODO: raise HardFault exception
166
164
  // console.error('Breakpoint!', code);
167
- this.stopped = true;
168
165
  };
169
166
  this.reset();
170
167
  }
@@ -339,26 +336,4 @@ export class RP2040 {
339
336
  step() {
340
337
  this.core.executeInstruction();
341
338
  }
342
- execute() {
343
- this.clock.resume();
344
- this.executeTimer = null;
345
- this.stopped = false;
346
- for (let i = 0; i < 100000 && !this.stopped && !this.core.waiting; i++) {
347
- this.core.executeInstruction();
348
- }
349
- if (!this.stopped) {
350
- this.executeTimer = setTimeout(() => this.execute(), 0);
351
- }
352
- }
353
- stop() {
354
- this.stopped = true;
355
- if (this.executeTimer != null) {
356
- clearTimeout(this.executeTimer);
357
- this.executeTimer = null;
358
- }
359
- this.clock.pause();
360
- }
361
- get executing() {
362
- return !this.stopped;
363
- }
364
339
  }
@@ -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,41 @@
1
+ import { SimulationClock } from './clock/simulation-clock.js';
2
+ import { RP2040 } from './rp2040.js';
3
+ export class Simulator {
4
+ constructor(clock = new SimulationClock()) {
5
+ this.clock = clock;
6
+ this.executeTimer = null;
7
+ this.stopped = true;
8
+ this.rp2040 = new RP2040(clock);
9
+ this.rp2040.onBreak = () => this.stop();
10
+ }
11
+ execute() {
12
+ const { rp2040, clock } = this;
13
+ this.executeTimer = null;
14
+ this.stopped = false;
15
+ const cycleNanos = 1e9 / 125000000; // 125 MHz
16
+ for (let i = 0; i < 1000000 && !this.stopped; i++) {
17
+ if (rp2040.core.waiting) {
18
+ const { nanosToNextAlarm } = clock;
19
+ clock.tick(nanosToNextAlarm);
20
+ i += nanosToNextAlarm / cycleNanos;
21
+ }
22
+ else {
23
+ const cycles = rp2040.core.executeInstruction();
24
+ clock.tick(cycles * cycleNanos);
25
+ }
26
+ }
27
+ if (!this.stopped) {
28
+ this.executeTimer = setTimeout(() => this.execute(), 0);
29
+ }
30
+ }
31
+ stop() {
32
+ this.stopped = true;
33
+ if (this.executeTimer != null) {
34
+ clearTimeout(this.executeTimer);
35
+ this.executeTimer = null;
36
+ }
37
+ }
38
+ get executing() {
39
+ return !this.stopped;
40
+ }
41
+ }
@@ -8,7 +8,7 @@ export declare class Timer32 {
8
8
  readonly clock: IClock;
9
9
  private baseFreq;
10
10
  private baseValue;
11
- private baseMicros;
11
+ private baseNanos;
12
12
  private topValue;
13
13
  private prescalerValue;
14
14
  private timerMode;
@@ -32,7 +32,7 @@ export declare class Timer32 {
32
32
  set frequency(value: number);
33
33
  get prescaler(): number;
34
34
  set prescaler(value: number);
35
- toMicros(cycles: number): number;
35
+ toNanos(cycles: number): number;
36
36
  get enable(): boolean;
37
37
  set enable(value: boolean);
38
38
  get mode(): TimerMode;
@@ -44,7 +44,7 @@ export declare class Timer32PeriodicAlarm {
44
44
  readonly callback: () => void;
45
45
  private targetValue;
46
46
  private enabled;
47
- private clockTimer?;
47
+ private clockAlarm;
48
48
  constructor(timer: Timer32, callback: () => void);
49
49
  get enable(): boolean;
50
50
  set enable(value: boolean);
@@ -9,7 +9,7 @@ export class Timer32 {
9
9
  this.clock = clock;
10
10
  this.baseFreq = baseFreq;
11
11
  this.baseValue = 0;
12
- this.baseMicros = 0;
12
+ this.baseNanos = 0;
13
13
  this.topValue = 0xffffffff;
14
14
  this.prescalerValue = 1;
15
15
  this.timerMode = TimerMode.Increment;
@@ -17,13 +17,13 @@ export class Timer32 {
17
17
  this.listeners = [];
18
18
  }
19
19
  reset() {
20
- this.baseMicros = this.clock.micros;
20
+ this.baseNanos = this.clock.nanos;
21
21
  this.baseValue = 0;
22
22
  this.updated();
23
23
  }
24
24
  set(value, zigZagDown = false) {
25
25
  this.baseValue = zigZagDown ? this.topValue * 2 - value : value;
26
- this.baseMicros = this.clock.micros;
26
+ this.baseNanos = this.clock.nanos;
27
27
  this.updated();
28
28
  }
29
29
  /**
@@ -36,12 +36,12 @@ export class Timer32 {
36
36
  this.baseValue += delta;
37
37
  }
38
38
  get rawCounter() {
39
- const { baseFreq, prescalerValue, baseMicros, baseValue, enabled, timerMode } = this;
39
+ const { baseFreq, prescalerValue, baseNanos, baseValue, enabled, timerMode } = this;
40
40
  if (!baseFreq || !prescalerValue || !enabled) {
41
41
  return this.baseValue;
42
42
  }
43
43
  const zigzag = timerMode == TimerMode.ZigZag;
44
- const ticks = ((this.clock.micros - baseMicros) / 1e6) * (baseFreq / prescalerValue);
44
+ const ticks = ((this.clock.nanos - baseNanos) / 1e9) * (baseFreq / prescalerValue);
45
45
  const topModulo = zigzag ? this.topValue * 2 : this.topValue + 1;
46
46
  const delta = timerMode == TimerMode.Decrement ? topModulo - (ticks % topModulo) : ticks;
47
47
  let currentValue = Math.round(baseValue + delta);
@@ -70,7 +70,7 @@ export class Timer32 {
70
70
  }
71
71
  set frequency(value) {
72
72
  this.baseValue = this.counter;
73
- this.baseMicros = this.clock.micros;
73
+ this.baseNanos = this.clock.nanos;
74
74
  this.baseFreq = value;
75
75
  this.updated();
76
76
  }
@@ -79,14 +79,14 @@ export class Timer32 {
79
79
  }
80
80
  set prescaler(value) {
81
81
  this.baseValue = this.counter;
82
- this.baseMicros = this.clock.micros;
82
+ this.baseNanos = this.clock.nanos;
83
83
  this.enabled = this.prescalerValue !== 0;
84
84
  this.prescalerValue = value;
85
85
  this.updated();
86
86
  }
87
- toMicros(cycles) {
87
+ toNanos(cycles) {
88
88
  const { baseFreq, prescalerValue } = this;
89
- return (cycles * 1e6) / (baseFreq / prescalerValue);
89
+ return (cycles * 1e9) / (baseFreq / prescalerValue);
90
90
  }
91
91
  get enable() {
92
92
  return this.enabled;
@@ -94,7 +94,7 @@ export class Timer32 {
94
94
  set enable(value) {
95
95
  if (value !== this.enabled) {
96
96
  if (value) {
97
- this.baseMicros = this.clock.micros;
97
+ this.baseNanos = this.clock.nanos;
98
98
  }
99
99
  else {
100
100
  this.baseValue = this.counter;
@@ -137,6 +137,7 @@ export class Timer32PeriodicAlarm {
137
137
  this.schedule();
138
138
  }
139
139
  };
140
+ this.clockAlarm = this.timer.clock.createAlarm(this.handleAlarm);
140
141
  timer.listeners.push(this.update);
141
142
  }
142
143
  get enable() {
@@ -191,13 +192,10 @@ export class Timer32PeriodicAlarm {
191
192
  cycleDelta = top + 1 - cycleDelta;
192
193
  }
193
194
  const cyclesToAlarm = cycleDelta >>> 0;
194
- const microsToAlarm = timer.toMicros(cyclesToAlarm);
195
- this.clockTimer = this.timer.clock.createTimer(microsToAlarm, this.handleAlarm);
195
+ const nanosToAlarm = timer.toNanos(cyclesToAlarm);
196
+ this.clockAlarm.schedule(nanosToAlarm);
196
197
  }
197
198
  cancel() {
198
- if (this.clockTimer) {
199
- this.timer.clock.deleteTimer(this.clockTimer);
200
- this.clockTimer = undefined;
201
- }
199
+ this.clockAlarm.cancel();
202
200
  }
203
201
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rp2040js",
3
- "version": "0.19.4",
3
+ "version": "1.0.0",
4
4
  "description": "Raspberry Pi Pico (RP2040) Emulator",
5
5
  "repository": "https://github.com/wokwi/rp2040js",
6
6
  "keywords": [
@@ -1,23 +0,0 @@
1
- import { IClock, IClockTimer } from './clock.js';
2
- export declare class ClockTimer implements IClockTimer {
3
- private micros;
4
- private callback;
5
- private jsTimer;
6
- private timeLeft;
7
- constructor(micros: number, callback: () => void);
8
- schedule(currentMicros: number): void;
9
- unschedule(): void;
10
- pause(currentMicros: number): void;
11
- resume(currentMicros: number): void;
12
- }
13
- export declare class RealtimeClock implements IClock {
14
- baseTime: number;
15
- pauseTime: number;
16
- paused: boolean;
17
- timers: Set<ClockTimer>;
18
- pause(): void;
19
- resume(): void;
20
- createTimer(deltaMicros: number, callback: () => void): ClockTimer;
21
- deleteTimer(timer: ClockTimer): void;
22
- get micros(): number;
23
- }
@@ -1,73 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RealtimeClock = exports.ClockTimer = void 0;
4
- const time_js_1 = require("../utils/time.js");
5
- class ClockTimer {
6
- constructor(micros, callback) {
7
- this.micros = micros;
8
- this.callback = callback;
9
- this.jsTimer = null;
10
- this.timeLeft = this.micros;
11
- }
12
- schedule(currentMicros) {
13
- this.jsTimer = setTimeout(this.callback, (this.micros - currentMicros) / 1000);
14
- }
15
- unschedule() {
16
- if (this.jsTimer) {
17
- clearTimeout(this.jsTimer);
18
- this.jsTimer = null;
19
- }
20
- }
21
- pause(currentMicros) {
22
- this.timeLeft = this.micros - currentMicros;
23
- this.unschedule();
24
- }
25
- resume(currentMicros) {
26
- this.micros = currentMicros + this.timeLeft;
27
- this.schedule(currentMicros);
28
- }
29
- }
30
- exports.ClockTimer = ClockTimer;
31
- class RealtimeClock {
32
- constructor() {
33
- this.baseTime = 0;
34
- this.pauseTime = 0;
35
- this.paused = true;
36
- this.timers = new Set();
37
- }
38
- pause() {
39
- if (!this.paused) {
40
- for (const timer of this.timers) {
41
- timer.pause(this.micros);
42
- }
43
- this.pauseTime = this.micros;
44
- this.paused = true;
45
- }
46
- }
47
- resume() {
48
- if (this.paused) {
49
- this.baseTime = (0, time_js_1.getCurrentMicroseconds)() - this.pauseTime;
50
- this.paused = false;
51
- for (const timer of this.timers) {
52
- timer.resume(this.micros);
53
- }
54
- }
55
- }
56
- createTimer(deltaMicros, callback) {
57
- const timer = new ClockTimer(this.micros + deltaMicros, () => {
58
- this.timers.delete(timer);
59
- callback();
60
- });
61
- timer.schedule(this.micros);
62
- this.timers.add(timer);
63
- return timer;
64
- }
65
- deleteTimer(timer) {
66
- timer.unschedule();
67
- this.timers.delete(timer);
68
- }
69
- get micros() {
70
- return (0, time_js_1.getCurrentMicroseconds)() - this.baseTime;
71
- }
72
- }
73
- exports.RealtimeClock = RealtimeClock;
@@ -1,23 +0,0 @@
1
- import { IClock, IClockTimer } from './clock.js';
2
- export declare class ClockTimer implements IClockTimer {
3
- private micros;
4
- private callback;
5
- private jsTimer;
6
- private timeLeft;
7
- constructor(micros: number, callback: () => void);
8
- schedule(currentMicros: number): void;
9
- unschedule(): void;
10
- pause(currentMicros: number): void;
11
- resume(currentMicros: number): void;
12
- }
13
- export declare class RealtimeClock implements IClock {
14
- baseTime: number;
15
- pauseTime: number;
16
- paused: boolean;
17
- timers: Set<ClockTimer>;
18
- pause(): void;
19
- resume(): void;
20
- createTimer(deltaMicros: number, callback: () => void): ClockTimer;
21
- deleteTimer(timer: ClockTimer): void;
22
- get micros(): number;
23
- }
@@ -1,68 +0,0 @@
1
- import { getCurrentMicroseconds } from '../utils/time.js';
2
- export class ClockTimer {
3
- constructor(micros, callback) {
4
- this.micros = micros;
5
- this.callback = callback;
6
- this.jsTimer = null;
7
- this.timeLeft = this.micros;
8
- }
9
- schedule(currentMicros) {
10
- this.jsTimer = setTimeout(this.callback, (this.micros - currentMicros) / 1000);
11
- }
12
- unschedule() {
13
- if (this.jsTimer) {
14
- clearTimeout(this.jsTimer);
15
- this.jsTimer = null;
16
- }
17
- }
18
- pause(currentMicros) {
19
- this.timeLeft = this.micros - currentMicros;
20
- this.unschedule();
21
- }
22
- resume(currentMicros) {
23
- this.micros = currentMicros + this.timeLeft;
24
- this.schedule(currentMicros);
25
- }
26
- }
27
- export class RealtimeClock {
28
- constructor() {
29
- this.baseTime = 0;
30
- this.pauseTime = 0;
31
- this.paused = true;
32
- this.timers = new Set();
33
- }
34
- pause() {
35
- if (!this.paused) {
36
- for (const timer of this.timers) {
37
- timer.pause(this.micros);
38
- }
39
- this.pauseTime = this.micros;
40
- this.paused = true;
41
- }
42
- }
43
- resume() {
44
- if (this.paused) {
45
- this.baseTime = getCurrentMicroseconds() - this.pauseTime;
46
- this.paused = false;
47
- for (const timer of this.timers) {
48
- timer.resume(this.micros);
49
- }
50
- }
51
- }
52
- createTimer(deltaMicros, callback) {
53
- const timer = new ClockTimer(this.micros + deltaMicros, () => {
54
- this.timers.delete(timer);
55
- callback();
56
- });
57
- timer.schedule(this.micros);
58
- this.timers.add(timer);
59
- return timer;
60
- }
61
- deleteTimer(timer) {
62
- timer.unschedule();
63
- this.timers.delete(timer);
64
- }
65
- get micros() {
66
- return getCurrentMicroseconds() - this.baseTime;
67
- }
68
- }