Skip to content

Commit 4922a3d

Browse files
committed
Reworked basic SPI frame format to be Header + Payload + Response.
Also adds details about LEDs, buttons and power control.
1 parent 3abe5b8 commit 4922a3d

2 files changed

Lines changed: 221 additions & 37 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@
44

55
* Skeleton application using knurling template
66
* Started work on command protocol definition
7-
7+
* LED Blinking Modes defined
8+
* SPI Frame Format revised

README.md

Lines changed: 219 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Firmware for the Neotron Board Management Controller (NBMC).
44

55
## Introduction
66

7-
The NMBC is an always-on microcontroller used on Neotron systems. It has very low idle power consumption, allowing it to remain powered up at all times. This lets it listen to button events from the Power and Reset buttons, and control the system LEDs, main `~RESET` signal and turn the main 5V Power Rail on and off. This lets your Neotron system have smart 'ATX PC' style features like a soft power button, and it also ensures that all power rails come up before the system is taken out of reset.
7+
The NBMC is an always-on microcontroller used on Neotron systems. It has very low idle power consumption, allowing it to remain powered up at all times. This lets it listen to button events from the Power and Reset buttons, and control the system LEDs, main `~RESET` signal and turn the main 5V Power Rail on and off. This lets your Neotron system have smart 'ATX PC' style features like a soft power button, and it also ensures that all power rails come up before the system is taken out of reset.
88

99
The NBMC appears to the main Neotron system processor as an Expansion Device. As such it sits on the SPI bus as a peripheral device, with a dedicated Chip Select line and a dedicated IRQ line. It provides to the system:
1010

@@ -71,66 +71,91 @@ This design should also be pin-compatible with the following SoCs (although this
7171

7272
Note that not all STM32 pins are 5V-tolerant, and the PS/2 protocol is a 5V open-collector system, so ensure that whichever part you pick has 5V-tolerant pins (marked `FT` or `FTt` in the datasheet) for the PS/2 signals. All of the parts above _should_ be OK, but they haven't been tested. Let us know if you try one!
7373

74-
## Communications Protocol - SPI Frames
74+
## SPI Communications Protocol
7575

7676
The SPI interface runs in SPI mode 0 (clock line idles low, data sampled on rising edge) at up to 16 MHz (TBD). It uses frames made up of 8-bit words.
7777

78-
To communicate with the NBMC, first take the Chip Select line (`SPI1_nCS`) low, then send the appropriate number of bytes. SPI is a full-duplex system, but in this system only one side is actually transferring useful data at any time.
78+
To communicate with the NBMC, the Host Processor must first take the Chip Select line (`SPI1_nCS`) low, then send a Header. SPI is a full-duplex system, but in this system only one side is actually transferring useful data at any time, so whilst the Header is being sent the Host will receive Padding Bytes in return (which can be discarded).
7979

80-
Once the appropriate number of bytes have been exchange, the Chip Select line must be raised for at least XXX microseconds, before another transfer is started.
80+
A Header specifies which direction the transfer is occurring (a read or a write), which register address is being access, and how many bytes are being transferred.
8181

82-
```
83-
+-----+-------------...-------------+----------------...---------------+
84-
| CMD | CLEN | Command Bytes 0..n | PADDING | Controller Out, Peripheral In (COPI)
85-
+-----+------+------...-------------+-----+------+---------...---------+
86-
| PADDING | RSP | RLEN | Response Bytes 0..n | Controller In, Peripheral Out (CIPO)
87-
+----------------...----------------+-----+------+---------...---------+
88-
```
82+
After the Header comes the Payload, and the Response Code. The Host must clock out the number of bytes specified in the header, plus one extra (for the response code). If the Host is performing a write, it must supply the data to be written (plus one padding byte for the response code). If the Host is performing a read, it must supply only padding bytes (which will be discarded), and it will receive the desired bytes in exchange, plus the response code.
83+
84+
The Host must leave at least (*TODO*) XXX microseconds between a Header Packet and a Payload Packet in order for the NBMC to construct and prepare the Payload.
8985

90-
The `CMD` byte is a command, given in the Table of Commands below. `RSP` is a response byte, given in the Table of Responses below.
86+
Once the Header, Payload and Response Code have been exchange, the Host may send another Header, or it may raise the Chip Select line to indicate that the transfers are complete.
9187

92-
Taking the Chip Select line low activates an Interrupt Routine. You must leave XXX microseconds (TBD) before starting the transfer in order to give the routine time to start. The various CMD bytes either read or write various registers in RAM. Once the Chip Select is raised, the system goes into its background processing, reading from the registers to set system outputs, and writing to registers based on system inputs.
88+
A 'write' exchange looks like this:
9389

94-
## Communications Protocol - Commands and Responses
90+
```
91+
Host NBMC
92+
| |
93+
|-------Header (2)---->|
94+
|<-----Padding-(2)-----|
95+
| |
96+
|------Payload-(N)---->|
97+
|<-----Padding-(N)-----|
98+
| |
99+
|------Padding-(1)---->|
100+
|<--Response Code-(1)--|
101+
```
95102

96-
### Table of Commands
103+
A 'read' exchange looks like this:
97104

98-
| Command Byte | Name |
99-
| ------------ | ----- |
100-
| 0x00 | PING |
101-
| 0x01 | READ |
102-
| 0x02 | WRITE |
105+
```
106+
Host NBMC
107+
| |
108+
|-------Header (2)---->|
109+
|<-----Padding-(2)-----|
110+
| |
111+
|------Padding-(N)---->|
112+
|<-----Payload-(N)-----|
113+
| |
114+
|------Padding-(1)---->|
115+
|<--Response Code-(1)--|
116+
```
103117

104-
### Table of Responses
118+
A Header is comprised of 16 bits (or two bytes), and is described in the following table.
105119

106-
| Response Byte | Name |
107-
| ------------- | --------------- |
108-
| 0x80 | OK |
109-
| 0x81 | Unknown Command |
110-
| 0xFF | Busy |
120+
| Byte | Bits | Meaning |
121+
| ---- | ---- | ------------------------------ |
122+
| 0 | 7 | Direction: 1 = read, 0 = write |
123+
| 0 | 6-0 | Register Address (0..128) |
124+
| 1 | 7-0 | Transfer Length (0..255) |
111125

112-
### PING Command
126+
Note that a *Transfer Length* of 0 is interpreted as being 256 bytes, rather than zero bytes (because that wouldn't make any sense - you can't request to transfer nothing).
113127

114-
This command just checks the NBMC is awake. There is no payload. A OK response is sent in return.
128+
Here are some example headers:
115129

116-
### READ Command
130+
* `0x8520` is a Read from Register Address 5 (0x05), of length 33 bytes.
131+
* `0x9700` is a Read from Register Address 23 (0x17), of length 256 bytes.
132+
* `0x7FFF` is a Write from Register Address 127 (0x7F), of length 255 bytes.
117133

118-
This command reads from an address in the NBMC. The payload is the 8-bit register address, followed by the 8-bit number of bytes to read. The `CLEN` must therefore be two.
134+
A Payload is simply the number of desired data bytes (as specified in the Header Packet). The meaning of these bytes will depend on the Register Address that was given in the Header.
119135

120-
### WRITE Command
136+
The possible values of the 'Response Code' byte are:
121137

122-
This command writes to an address in the NBMC. The payload is the 8-bit register address, followed by the 8-bit number of bytes to write, followed by the bytes themselves (up to 253). The `CLEN` must therefore be 2 + the number of bytes written.
138+
| Value | Meaning |
139+
| ----- | ------------------------ |
140+
| 0x00 | Transfer OK |
141+
| 0x01 | Data underflow/overflow |
142+
| 0x02 | Unknown Register Address |
143+
| 0x03 | Unsupported Length |
123144

124-
### Table of Registers
145+
## System Registers
125146

126147
| Address | Name | Type | Contains | Length |
127148
| ------- | ------------------------------------- | ----- | -------------------------------------------------------- | ------ |
128149
| 0x00 | Firmware Version | RO | The NBMC firmware version, as a null-padded UTF-8 string | 64 |
129150
| 0x01 | Interrupt Status | R/W1C | Which interrupts are currently active, as a bitmask. | 2 |
130151
| 0x02 | Interrupt Control | R/W | Which interrupts are currently enabled, as a bitmask. | 2 |
131-
| 0x03 | LED Control | R/W | Settings for the LED outputs | 1 |
132-
| 0x04 | Button Status | RO | The current state of the buttons | 1 |
133-
| 0x05 | System Temperature | RO | Temperature in °C, as an `i8` | 1 |
152+
| 0x03 | LED 0 Control | R/W | Settings for the LED 0 output | 1 |
153+
| 0x04 | LED 1 Control | R/W | Settings for the LED 1 output | 1 |
154+
| 0x05 | Button Status | RO | The current state of the buttons | 1 |
155+
| 0x06 | System Temperature | RO | Temperature in °C, as an `i8` | 1 |
156+
| 0x07 | System Voltage (3.3V rail) | RO | Voltage in Volts/32, as a `u8` | 1 |
157+
| 0x08 | System Voltage (5.0V rail) | RO | Voltage in Volts/32, as a `u8` | 1 |
158+
| 0x09 | Power Control | RW | Enable/disable the power supply | 1 |
134159
| 0x10 | UART Receive/Transmit Buffer | FIFO | Data received/to be sent over the UART | max 64 |
135160
| 0x11 | UART FIFO Control | R/W | Settings for the UART FIFO | 1 |
136161
| 0x12 | UART Control | R/W | Settings for the UART | 1 |
@@ -161,6 +186,164 @@ This read-only register returns the firmware version of the NBMC, as a UTF-8 str
161186

162187
An official release will have a version string of the form `tags/v1.2.3`. An unofficial release might be `heads/develop-dirty`. It is not recommended that you rely on these formats or attempt to parse the version string. It is however useful if you can quote this string when reporting issues with the firmware.
163188

189+
### Address 0x01 - Interrupt Status
190+
191+
This eight bit register indicates which Interrupts are currently 'active'. An Interrupt will remain 'active' until a word is written to this register with a 1 bit in the relevant position.
192+
193+
| Bit | Interrupt |
194+
| --- | -------------------------- |
195+
| 7 | Voltage Alarm |
196+
| 6 | Button State Change |
197+
| 5 | UART TX Empty |
198+
| 4 | UART RX Not Empty |
199+
| 3 | I²C TX Empty |
200+
| 2 | I²C RX Not Empty |
201+
| 1 | PS/2 Mouse RX Not Empty |
202+
| 0 | PS/2 Keyboard RX Not Empty |
203+
204+
### Address 0x02 - Interrupt Control
205+
206+
This eight bit register indicates which Interrupts are currently 'enabled'. The IRQ_nHOST signal is a level interrupt and it will be active (LOW) whenever the value in the Interrupt Control register ANDed with the Interrupt Status register is non-zero.
207+
208+
The bits have the same ordering as the Interrupt Status register.
209+
210+
### Address 0x03 - LED 0 Control
211+
212+
This eight-bit register controls the LED 0 attached to the NBMC
213+
214+
| Bits | Meaning |
215+
| ---- | -------------------------------------------------------------- |
216+
| 7-4 | LED Cycle Duration: in 100 millisecond units |
217+
| 3-1 | LED Blink Ratio: 0 = solid, 1 = 10/90, 2 = 50/50, 3 = one-shot |
218+
| 0 | LED Enabled: 0 = off, 1 = on |
219+
220+
One-shot mode means that if the LED is set to 'on', it will automatically set itself to 'off' after the specified period. This can be useful for creating activity indicators - you could set an LED to 'one-shot' and set it 'on' whenever disk activity occurs, knowing that it will turn off automatically soon after if there is no further activity. Writing a value to this register whilst a one-shot is in progress will cancel the existing one-shot and start a new one (if the new value indicates it should do so).
221+
222+
A Blink Ratio of 90/10, means that the LED will be on for 10% of the given cycle duration, and off for the other 90%.
223+
224+
A Blink Ratio of 50/50, means that the LED will be on for 50% of the given cycle duration, and off for the other 50%.
225+
226+
The Cycle Duration is the total time of an LED Cycle or, in one-shot mode, the timeout after which the LED sets itself to off. Note that because '0 ms' doesn't make sense, we take a value of zero in this register to be a value of 16 (i.e. 1600ms).
227+
228+
#### Example 1
229+
230+
* LED Cycle Duration = 5 (500ms)
231+
* LED Blink Ratio = 2 (50/50)
232+
* LED Enabled = 1 (on)
233+
234+
The LED will blink twice a second, 250ms at a time.
235+
236+
#### Example 2
237+
238+
* LED Cycle Duration = 2 (200ms)
239+
* LED Blink Ratio = 1 (10/90)
240+
* LED Enabled = 1 (on)
241+
242+
The LED will blink five times a second, 20ms at a time.
243+
244+
### Address 0x04 - LED 1 Control
245+
246+
See *Address 0x03 - LED 0 Control*
247+
248+
### Address 0x05 - Button Status
249+
250+
This eight-bit register indicates the state of the power button.
251+
252+
Note that if the power button is held down for three seconds, the system will power-off instantly, regardless of what the host does.
253+
254+
Note also that is it not possible to sample the reset button - pressing the reset button will instantly assert the system reset line, rebooting the Host.
255+
256+
| Bits | Meaning |
257+
| ---- | ------------------------------------- |
258+
| 7-1 | Reserved for future use |
259+
| 0 | Power Button: 0 = normal, 1 = pressed |
260+
261+
### Address 0x06 - System Temperature
262+
263+
This eight-bit register provides the current system temperature in °C, as measured on the STM32's internal temperature sensor. It is updated around once a second.
264+
265+
### Address 0x07 - System Voltage (3.3V rail)
266+
267+
This eight-bit register provides the current 3.3V rail voltage in units of 1/32 of a Volt. It is updated around once a second. A value of 105 (3.28V) to 106 (3.31V) is nominal. An interrupt is raised when the value exceeds 3.63V (116) or is lower than 2.97V (95).
268+
269+
### Address 0x08 - System Voltage (5.0V rail)
270+
271+
This eight-bit register provides the current 3.3V rail voltage in units of 1/32 of a Volt. It is updated around once a second. A value of 160 (5.00V) is nominal. An interrupt is raised when the value exceeds 5.5V (176) or is lower than 4.5V (144).
272+
273+
### Address 0x09 - Power Control
274+
275+
This eight-bit register controls the main DC/DC power supply unit. The Host should disable the DC/DC supply (by writing zero here) if it wishes to power down.
276+
277+
| Bits | Meaning |
278+
| ---- | ------------------------------ |
279+
| 7-1 | Reserved for future use |
280+
| 0 | DC/DC control: 0 = off, 1 = on |
281+
282+
### Address 0x10 - UART Receive/Transmit Buffer
283+
284+
TODO
285+
286+
### Address 0x11 - UART FIFO Control
287+
288+
TODO
289+
290+
### Address 0x12 - UART Control
291+
292+
TODO
293+
294+
### Address 0x13 - UART Status
295+
296+
TODO
297+
298+
### Address 0x14 - UART Baud Rate
299+
300+
TODO
301+
302+
### Address 0x20 - PS/2 Keyboard Receive/Transmit Buffer
303+
304+
TODO
305+
306+
### Address 0x21 - PS/2 Keyboard Control
307+
308+
TODO
309+
310+
### Address 0x22 - PS/2 Keyboard Status
311+
312+
TODO
313+
314+
### Address 0x30 - PS/2 Mouse Receive/Transmit Buffer
315+
316+
TODO
317+
318+
### Address 0x31 - PS/2 Mouse Control
319+
320+
TODO
321+
322+
### Address 0x32 - PS/2 Mouse Status
323+
324+
TODO
325+
326+
### Address 0x50 - I²C Receive/Transmit Buffer
327+
328+
TODO
329+
330+
### Address 0x51 - I²C FIFO Control
331+
332+
TODO
333+
334+
### Address 0x52 - I²C Control
335+
336+
TODO
337+
338+
### Address 0x53 - I²C Status
339+
340+
TODO
341+
342+
### Address 0x54 - I²C Baud Rate
343+
344+
TODO
345+
346+
164347
## Build Requirements
165348

166349
1. rustup and Rust

0 commit comments

Comments
 (0)