rp2040js 0.18.2 → 0.19.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.
@@ -9,6 +9,9 @@ const SSI_DR0 = 0x00000060;
9
9
  const SSI_SR_TFNF_BITS = 0x00000002;
10
10
  const SSI_SR_TFE_BITS = 0x00000004;
11
11
  const SSI_SR_RFNE_BITS = 0x00000008;
12
+ /** Identification register */
13
+ const SSI_IDR = 0x00000058;
14
+ const SSI_VERSION_ID = 0x0000005c;
12
15
  const CMD_READ_STATUS = 0x05;
13
16
  class RPSSI extends peripheral_js_1.BasePeripheral {
14
17
  constructor() {
@@ -23,6 +26,10 @@ class RPSSI extends peripheral_js_1.BasePeripheral {
23
26
  return 0;
24
27
  case SSI_SR:
25
28
  return SSI_SR_TFE_BITS | SSI_SR_RFNE_BITS | SSI_SR_TFNF_BITS;
29
+ case SSI_IDR:
30
+ return 0x51535049;
31
+ case SSI_VERSION_ID:
32
+ return 0x3430312a;
26
33
  case SSI_DR0:
27
34
  return this.dr0;
28
35
  }
@@ -32,6 +32,7 @@ const RXE = 1 << 9;
32
32
  const TXE = 1 << 8;
33
33
  const UARTEN = 1 << 0;
34
34
  // Interrupt bits
35
+ const UARTTXINTR = 1 << 5;
35
36
  const UARTRXINTR = 1 << 4;
36
37
  class RPUART extends peripheral_js_1.BasePeripheral {
37
38
  constructor(rp2040, name, irq, dreq) {
@@ -83,6 +84,8 @@ class RPUART extends peripheral_js_1.BasePeripheral {
83
84
  return (this.rxFIFO.full ? RXFF : 0) | (this.rxFIFO.empty ? RXFE : 0) | TXFE;
84
85
  }
85
86
  checkInterrupts() {
87
+ // TODO We should actually implement a proper FIFO for TX
88
+ this.interruptStatus |= UARTTXINTR;
86
89
  this.rp2040.setInterrupt(this.irq, !!(this.interruptStatus & this.interruptMask));
87
90
  }
88
91
  feedByte(value) {
@@ -97,8 +100,11 @@ class RPUART extends peripheral_js_1.BasePeripheral {
97
100
  const value = this.rxFIFO.pull();
98
101
  if (!this.rxFIFO.empty) {
99
102
  this.interruptStatus |= UARTRXINTR;
100
- this.checkInterrupts();
101
103
  }
104
+ else {
105
+ this.interruptStatus &= ~UARTRXINTR;
106
+ }
107
+ this.checkInterrupts();
102
108
  return value;
103
109
  }
104
110
  case UARTFR:
@@ -0,0 +1,19 @@
1
+ import { RP2040 } from '../rp2040.js';
2
+ import { Timer32, Timer32PeriodicAlarm } from '../utils/timer32.js';
3
+ import { BasePeripheral, Peripheral } from './peripheral.js';
4
+ export declare class RPWatchdog extends BasePeripheral implements Peripheral {
5
+ readonly timer: Timer32;
6
+ readonly alarm: Timer32PeriodicAlarm;
7
+ readonly scratchData: Uint32Array;
8
+ private enable;
9
+ private tickEnable;
10
+ private reason;
11
+ private pauseDbg0;
12
+ private pauseDbg1;
13
+ private pauseJtag;
14
+ /** Called when the watchdog triggers - override with your own soft reset implementation */
15
+ onWatchdogTrigger: () => void;
16
+ constructor(rp2040: RP2040, name: string);
17
+ readUint32(offset: number): number;
18
+ writeUint32(offset: number, value: number): void;
19
+ }
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RPWatchdog = void 0;
4
+ const timer32_js_1 = require("../utils/timer32.js");
5
+ const peripheral_js_1 = require("./peripheral.js");
6
+ const CTRL = 0x00; // Control register
7
+ const LOAD = 0x04; // Load the watchdog timer.
8
+ const REASON = 0x08; // Logs the reason for the last reset.
9
+ const SCRATCH0 = 0x0c; // Scratch register
10
+ const SCRATCH1 = 0x10; // Scratch register
11
+ const SCRATCH2 = 0x14; // Scratch register
12
+ const SCRATCH3 = 0x18; // Scratch register
13
+ const SCRATCH4 = 0x1c; // Scratch register
14
+ const SCRATCH5 = 0x20; // Scratch register
15
+ const SCRATCH6 = 0x24; // Scratch register
16
+ const SCRATCH7 = 0x28; // Scratch register
17
+ const TICK = 0x2c; // Controls the tick generator
18
+ // CTRL bits:
19
+ const TRIGGER = 1 << 31;
20
+ const ENABLE = 1 << 30;
21
+ const PAUSE_DBG1 = 1 << 26;
22
+ const PAUSE_DBG0 = 1 << 25;
23
+ const PAUSE_JTAG = 1 << 24;
24
+ const TIME_MASK = 0xffffff;
25
+ const TIME_SHIFT = 0;
26
+ // LOAD bits
27
+ const LOAD_MASK = 0xffffff;
28
+ const LOAD_SHIFT = 0;
29
+ // REASON bits:
30
+ const FORCE = 1 << 1;
31
+ const TIMER = 1 << 0;
32
+ // TICK bits:
33
+ const COUNT_MASK = 0x1ff;
34
+ const COUNT_SHIFT = 11;
35
+ const RUNNING = 1 << 10;
36
+ const TICK_ENABLE = 1 << 9;
37
+ const CYCLES_MASK = 0x1ff;
38
+ const CYCLES_SHIFT = 0;
39
+ const TICK_FREQUENCY = 2000000; // Actually 1 MHz, but due to errata RP2040-E1, the timer is decremented twice per tick
40
+ class RPWatchdog extends peripheral_js_1.BasePeripheral {
41
+ // User provided
42
+ constructor(rp2040, name) {
43
+ super(rp2040, name);
44
+ this.scratchData = new Uint32Array(8);
45
+ this.enable = false;
46
+ this.tickEnable = true;
47
+ this.reason = 0;
48
+ this.pauseDbg0 = true;
49
+ this.pauseDbg1 = true;
50
+ this.pauseJtag = true;
51
+ /** Called when the watchdog triggers - override with your own soft reset implementation */
52
+ this.onWatchdogTrigger = () => {
53
+ this.rp2040.logger.warn(this.name, 'Watchdog triggered, but no reset handler provided');
54
+ };
55
+ this.timer = new timer32_js_1.Timer32(rp2040.clock, TICK_FREQUENCY);
56
+ this.timer.mode = timer32_js_1.TimerMode.Decrement;
57
+ this.timer.enable = false;
58
+ this.alarm = new timer32_js_1.Timer32PeriodicAlarm(this.timer, () => {
59
+ var _a;
60
+ this.reason = TIMER;
61
+ (_a = this.onWatchdogTrigger) === null || _a === void 0 ? void 0 : _a.call(this);
62
+ });
63
+ this.alarm.target = 0;
64
+ this.alarm.enable = false;
65
+ }
66
+ readUint32(offset) {
67
+ switch (offset) {
68
+ case CTRL:
69
+ return ((this.timer.enable ? ENABLE : 0) |
70
+ (this.pauseDbg0 ? PAUSE_DBG0 : 0) |
71
+ (this.pauseDbg1 ? PAUSE_DBG1 : 0) |
72
+ (this.pauseJtag ? PAUSE_JTAG : 0) |
73
+ ((this.timer.counter & TIME_MASK) << TIME_SHIFT));
74
+ case REASON:
75
+ return this.reason;
76
+ case SCRATCH0:
77
+ case SCRATCH1:
78
+ case SCRATCH2:
79
+ case SCRATCH3:
80
+ case SCRATCH4:
81
+ case SCRATCH5:
82
+ case SCRATCH6:
83
+ case SCRATCH7:
84
+ return this.scratchData[(offset - SCRATCH0) >> 2];
85
+ case TICK:
86
+ // TODO COUNT bits
87
+ return this.tickEnable ? RUNNING | TICK_ENABLE : 0;
88
+ }
89
+ return super.readUint32(offset);
90
+ }
91
+ writeUint32(offset, value) {
92
+ var _a;
93
+ switch (offset) {
94
+ case CTRL:
95
+ if (value & TRIGGER) {
96
+ this.reason = FORCE;
97
+ (_a = this.onWatchdogTrigger) === null || _a === void 0 ? void 0 : _a.call(this);
98
+ }
99
+ this.enable = !!(value & ENABLE);
100
+ this.timer.enable = this.enable && this.tickEnable;
101
+ this.alarm.enable = this.enable && this.tickEnable;
102
+ this.pauseDbg0 = !!(value & PAUSE_DBG0);
103
+ this.pauseDbg1 = !!(value & PAUSE_DBG1);
104
+ this.pauseJtag = !!(value & PAUSE_JTAG);
105
+ break;
106
+ case LOAD:
107
+ this.timer.set((value >>> LOAD_SHIFT) & LOAD_MASK);
108
+ break;
109
+ case SCRATCH0:
110
+ case SCRATCH1:
111
+ case SCRATCH2:
112
+ case SCRATCH3:
113
+ case SCRATCH4:
114
+ case SCRATCH5:
115
+ case SCRATCH6:
116
+ case SCRATCH7:
117
+ this.scratchData[(offset - SCRATCH0) >> 2] = value;
118
+ break;
119
+ case TICK:
120
+ this.tickEnable = !!(value & TICK_ENABLE);
121
+ this.timer.enable = this.enable && this.tickEnable;
122
+ this.alarm.enable = this.enable && this.tickEnable;
123
+ // TODO - handle CYCLES (tick also affectes timer)
124
+ break;
125
+ default:
126
+ super.writeUint32(offset, value);
127
+ }
128
+ }
129
+ }
130
+ exports.RPWatchdog = RPWatchdog;
@@ -26,6 +26,7 @@ const tbman_js_1 = require("./peripherals/tbman.js");
26
26
  const timer_js_1 = require("./peripherals/timer.js");
27
27
  const uart_js_1 = require("./peripherals/uart.js");
28
28
  const usb_js_1 = require("./peripherals/usb.js");
29
+ const watchdog_js_1 = require("./peripherals/watchdog.js");
29
30
  const sio_js_1 = require("./sio.js");
30
31
  const logging_js_1 = require("./utils/logging.js");
31
32
  exports.FLASH_START_ADDRESS = 0x10000000;
@@ -150,7 +151,7 @@ class RP2040 {
150
151
  0x4004c: this.adc,
151
152
  0x40050: this.pwm,
152
153
  0x40054: new timer_js_1.RPTimer(this, 'TIMER_BASE'),
153
- 0x40058: new peripheral_js_1.UnimplementedPeripheral(this, 'WATCHDOG_BASE'),
154
+ 0x40058: new watchdog_js_1.RPWatchdog(this, 'WATCHDOG_BASE'),
154
155
  0x4005c: new rtc_js_1.RP2040RTC(this, 'RTC_BASE'),
155
156
  0x40060: new peripheral_js_1.UnimplementedPeripheral(this, 'ROSC_BASE'),
156
157
  0x40064: new peripheral_js_1.UnimplementedPeripheral(this, 'VREG_AND_CHIP_RESET_BASE'),
@@ -6,6 +6,9 @@ const SSI_DR0 = 0x00000060;
6
6
  const SSI_SR_TFNF_BITS = 0x00000002;
7
7
  const SSI_SR_TFE_BITS = 0x00000004;
8
8
  const SSI_SR_RFNE_BITS = 0x00000008;
9
+ /** Identification register */
10
+ const SSI_IDR = 0x00000058;
11
+ const SSI_VERSION_ID = 0x0000005c;
9
12
  const CMD_READ_STATUS = 0x05;
10
13
  export class RPSSI extends BasePeripheral {
11
14
  constructor() {
@@ -20,6 +23,10 @@ export class RPSSI extends BasePeripheral {
20
23
  return 0;
21
24
  case SSI_SR:
22
25
  return SSI_SR_TFE_BITS | SSI_SR_RFNE_BITS | SSI_SR_TFNF_BITS;
26
+ case SSI_IDR:
27
+ return 0x51535049;
28
+ case SSI_VERSION_ID:
29
+ return 0x3430312a;
23
30
  case SSI_DR0:
24
31
  return this.dr0;
25
32
  }
@@ -29,6 +29,7 @@ const RXE = 1 << 9;
29
29
  const TXE = 1 << 8;
30
30
  const UARTEN = 1 << 0;
31
31
  // Interrupt bits
32
+ const UARTTXINTR = 1 << 5;
32
33
  const UARTRXINTR = 1 << 4;
33
34
  export class RPUART extends BasePeripheral {
34
35
  constructor(rp2040, name, irq, dreq) {
@@ -80,6 +81,8 @@ export class RPUART extends BasePeripheral {
80
81
  return (this.rxFIFO.full ? RXFF : 0) | (this.rxFIFO.empty ? RXFE : 0) | TXFE;
81
82
  }
82
83
  checkInterrupts() {
84
+ // TODO We should actually implement a proper FIFO for TX
85
+ this.interruptStatus |= UARTTXINTR;
83
86
  this.rp2040.setInterrupt(this.irq, !!(this.interruptStatus & this.interruptMask));
84
87
  }
85
88
  feedByte(value) {
@@ -94,8 +97,11 @@ export class RPUART extends BasePeripheral {
94
97
  const value = this.rxFIFO.pull();
95
98
  if (!this.rxFIFO.empty) {
96
99
  this.interruptStatus |= UARTRXINTR;
97
- this.checkInterrupts();
98
100
  }
101
+ else {
102
+ this.interruptStatus &= ~UARTRXINTR;
103
+ }
104
+ this.checkInterrupts();
99
105
  return value;
100
106
  }
101
107
  case UARTFR:
@@ -0,0 +1,19 @@
1
+ import { RP2040 } from '../rp2040.js';
2
+ import { Timer32, Timer32PeriodicAlarm } from '../utils/timer32.js';
3
+ import { BasePeripheral, Peripheral } from './peripheral.js';
4
+ export declare class RPWatchdog extends BasePeripheral implements Peripheral {
5
+ readonly timer: Timer32;
6
+ readonly alarm: Timer32PeriodicAlarm;
7
+ readonly scratchData: Uint32Array;
8
+ private enable;
9
+ private tickEnable;
10
+ private reason;
11
+ private pauseDbg0;
12
+ private pauseDbg1;
13
+ private pauseJtag;
14
+ /** Called when the watchdog triggers - override with your own soft reset implementation */
15
+ onWatchdogTrigger: () => void;
16
+ constructor(rp2040: RP2040, name: string);
17
+ readUint32(offset: number): number;
18
+ writeUint32(offset: number, value: number): void;
19
+ }
@@ -0,0 +1,126 @@
1
+ import { Timer32, Timer32PeriodicAlarm, TimerMode } from '../utils/timer32.js';
2
+ import { BasePeripheral } from './peripheral.js';
3
+ const CTRL = 0x00; // Control register
4
+ const LOAD = 0x04; // Load the watchdog timer.
5
+ const REASON = 0x08; // Logs the reason for the last reset.
6
+ const SCRATCH0 = 0x0c; // Scratch register
7
+ const SCRATCH1 = 0x10; // Scratch register
8
+ const SCRATCH2 = 0x14; // Scratch register
9
+ const SCRATCH3 = 0x18; // Scratch register
10
+ const SCRATCH4 = 0x1c; // Scratch register
11
+ const SCRATCH5 = 0x20; // Scratch register
12
+ const SCRATCH6 = 0x24; // Scratch register
13
+ const SCRATCH7 = 0x28; // Scratch register
14
+ const TICK = 0x2c; // Controls the tick generator
15
+ // CTRL bits:
16
+ const TRIGGER = 1 << 31;
17
+ const ENABLE = 1 << 30;
18
+ const PAUSE_DBG1 = 1 << 26;
19
+ const PAUSE_DBG0 = 1 << 25;
20
+ const PAUSE_JTAG = 1 << 24;
21
+ const TIME_MASK = 0xffffff;
22
+ const TIME_SHIFT = 0;
23
+ // LOAD bits
24
+ const LOAD_MASK = 0xffffff;
25
+ const LOAD_SHIFT = 0;
26
+ // REASON bits:
27
+ const FORCE = 1 << 1;
28
+ const TIMER = 1 << 0;
29
+ // TICK bits:
30
+ const COUNT_MASK = 0x1ff;
31
+ const COUNT_SHIFT = 11;
32
+ const RUNNING = 1 << 10;
33
+ const TICK_ENABLE = 1 << 9;
34
+ const CYCLES_MASK = 0x1ff;
35
+ const CYCLES_SHIFT = 0;
36
+ const TICK_FREQUENCY = 2000000; // Actually 1 MHz, but due to errata RP2040-E1, the timer is decremented twice per tick
37
+ export class RPWatchdog extends BasePeripheral {
38
+ // User provided
39
+ constructor(rp2040, name) {
40
+ super(rp2040, name);
41
+ this.scratchData = new Uint32Array(8);
42
+ this.enable = false;
43
+ this.tickEnable = true;
44
+ this.reason = 0;
45
+ this.pauseDbg0 = true;
46
+ this.pauseDbg1 = true;
47
+ this.pauseJtag = true;
48
+ /** Called when the watchdog triggers - override with your own soft reset implementation */
49
+ this.onWatchdogTrigger = () => {
50
+ this.rp2040.logger.warn(this.name, 'Watchdog triggered, but no reset handler provided');
51
+ };
52
+ this.timer = new Timer32(rp2040.clock, TICK_FREQUENCY);
53
+ this.timer.mode = TimerMode.Decrement;
54
+ this.timer.enable = false;
55
+ this.alarm = new Timer32PeriodicAlarm(this.timer, () => {
56
+ var _a;
57
+ this.reason = TIMER;
58
+ (_a = this.onWatchdogTrigger) === null || _a === void 0 ? void 0 : _a.call(this);
59
+ });
60
+ this.alarm.target = 0;
61
+ this.alarm.enable = false;
62
+ }
63
+ readUint32(offset) {
64
+ switch (offset) {
65
+ case CTRL:
66
+ return ((this.timer.enable ? ENABLE : 0) |
67
+ (this.pauseDbg0 ? PAUSE_DBG0 : 0) |
68
+ (this.pauseDbg1 ? PAUSE_DBG1 : 0) |
69
+ (this.pauseJtag ? PAUSE_JTAG : 0) |
70
+ ((this.timer.counter & TIME_MASK) << TIME_SHIFT));
71
+ case REASON:
72
+ return this.reason;
73
+ case SCRATCH0:
74
+ case SCRATCH1:
75
+ case SCRATCH2:
76
+ case SCRATCH3:
77
+ case SCRATCH4:
78
+ case SCRATCH5:
79
+ case SCRATCH6:
80
+ case SCRATCH7:
81
+ return this.scratchData[(offset - SCRATCH0) >> 2];
82
+ case TICK:
83
+ // TODO COUNT bits
84
+ return this.tickEnable ? RUNNING | TICK_ENABLE : 0;
85
+ }
86
+ return super.readUint32(offset);
87
+ }
88
+ writeUint32(offset, value) {
89
+ var _a;
90
+ switch (offset) {
91
+ case CTRL:
92
+ if (value & TRIGGER) {
93
+ this.reason = FORCE;
94
+ (_a = this.onWatchdogTrigger) === null || _a === void 0 ? void 0 : _a.call(this);
95
+ }
96
+ this.enable = !!(value & ENABLE);
97
+ this.timer.enable = this.enable && this.tickEnable;
98
+ this.alarm.enable = this.enable && this.tickEnable;
99
+ this.pauseDbg0 = !!(value & PAUSE_DBG0);
100
+ this.pauseDbg1 = !!(value & PAUSE_DBG1);
101
+ this.pauseJtag = !!(value & PAUSE_JTAG);
102
+ break;
103
+ case LOAD:
104
+ this.timer.set((value >>> LOAD_SHIFT) & LOAD_MASK);
105
+ break;
106
+ case SCRATCH0:
107
+ case SCRATCH1:
108
+ case SCRATCH2:
109
+ case SCRATCH3:
110
+ case SCRATCH4:
111
+ case SCRATCH5:
112
+ case SCRATCH6:
113
+ case SCRATCH7:
114
+ this.scratchData[(offset - SCRATCH0) >> 2] = value;
115
+ break;
116
+ case TICK:
117
+ this.tickEnable = !!(value & TICK_ENABLE);
118
+ this.timer.enable = this.enable && this.tickEnable;
119
+ this.alarm.enable = this.enable && this.tickEnable;
120
+ // TODO - handle CYCLES (tick also affectes timer)
121
+ break;
122
+ default:
123
+ super.writeUint32(offset, value);
124
+ }
125
+ }
126
+ }
@@ -23,6 +23,7 @@ import { RPTBMAN } from './peripherals/tbman.js';
23
23
  import { RPTimer } from './peripherals/timer.js';
24
24
  import { RPUART } from './peripherals/uart.js';
25
25
  import { RPUSBController } from './peripherals/usb.js';
26
+ import { RPWatchdog } from './peripherals/watchdog.js';
26
27
  import { RPSIO } from './sio.js';
27
28
  import { ConsoleLogger, LogLevel } from './utils/logging.js';
28
29
  export const FLASH_START_ADDRESS = 0x10000000;
@@ -147,7 +148,7 @@ export class RP2040 {
147
148
  0x4004c: this.adc,
148
149
  0x40050: this.pwm,
149
150
  0x40054: new RPTimer(this, 'TIMER_BASE'),
150
- 0x40058: new UnimplementedPeripheral(this, 'WATCHDOG_BASE'),
151
+ 0x40058: new RPWatchdog(this, 'WATCHDOG_BASE'),
151
152
  0x4005c: new RP2040RTC(this, 'RTC_BASE'),
152
153
  0x40060: new UnimplementedPeripheral(this, 'ROSC_BASE'),
153
154
  0x40064: new UnimplementedPeripheral(this, 'VREG_AND_CHIP_RESET_BASE'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rp2040js",
3
- "version": "0.18.2",
3
+ "version": "0.19.1",
4
4
  "description": "Raspberry Pi Pico (RP2040) Emulator",
5
5
  "repository": "https://github.com/wokwi/rp2040js",
6
6
  "keywords": [