Skip to content

Commit 6255fe7

Browse files
committed
SPM works!
Self programming works Sketch can be uploaded as bootloader directly from Arduino (using external programmer) Updated Readme Code is even smaller than previously Cleaned up Writer (and changed baudrate) Added LED to Reader to indicate bootloader working (only for testing)
1 parent 31f63fe commit 6255fe7

File tree

7 files changed

+99
-136
lines changed

7 files changed

+99
-136
lines changed

MULoaderReader/MULoaderReader.ino

Lines changed: 70 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,36 @@
11
#include <SPI.h>
22
#include "RC522.h"
3+
#include <Arduino.h>
34
#include <avr/boot.h>
45

5-
/* Move this to AVR Studio */
6-
7-
#define S_DEBUG
6+
/* 3760 bytes free after removing serial */
7+
/* Compared with 5624 bytes it's a huge difference */
8+
//#define S_DEBUG
89

910
void setup() {
10-
RC522 rfid(10);
11+
cli();
12+
pinMode(A1, OUTPUT);
13+
digitalWrite(A1, HIGH);
1114
SPI.begin();
15+
RC522 rfid(10);
16+
rfid.PCD_Init();
17+
1218
#ifdef S_DEBUG
13-
Serial.begin(2000000);
19+
Serial.begin(115200);
1420
Serial.println(F("MostUseless Bootloader Reader"));
1521
#endif
16-
rfid.PCD_Init();
17-
18-
RC522::MIFARE_Key key;
19-
memset(key.keyByte, 0xFF, 6);
20-
2122

2223
/* Jump to code after timeout */
23-
while (millis() < 10000 && !rfid.PICC_IsNewCardPresent());
24-
if (millis() > 10000) asm("jmp 0x0000");
25-
24+
/* Timeout doesn't work but lol, the rest of stuff works */
25+
while (millis() < 1000 && !rfid.PICC_IsNewCardPresent());
26+
if (millis() >= 1000) {
27+
digitalWrite(A1, LOW);
28+
asm("jmp 0");
29+
}
2630
while (!rfid.PICC_ReadCardSerial());
2731

32+
digitalWrite(A1, LOW);
33+
2834
/* Sketch metadata */
2935
uint16_t siz = 0;
3036
uint8_t parts = 0;
@@ -38,15 +44,19 @@ void setup() {
3844
uint8_t memptr = 0;
3945

4046
/*
41-
We don't need to worry about extra data in last
42-
page if we already set buffer as empty :)
47+
We don't need to worry about extra data in last
48+
page if we already set buffer as empty :)
4349
*/
44-
uint8_t pageBuffer[256];
50+
volatile static uint8_t pageBuffer[256];
4551
memset(pageBuffer, 0xFF, 256);
4652

53+
/* Generic key */
54+
RC522::MIFARE_Key key;
55+
memset(key.keyByte, 0xFF, 6);
56+
4757
/*
48-
Reading every block and using page offset
49-
to save progress if more parts are needed
58+
Reading every block and using page offset
59+
to save progress if more parts are needed
5060
*/
5161

5262
for (uint8_t block = 1; block < blocks; block++) {
@@ -56,18 +66,18 @@ void setup() {
5666
}
5767

5868
uint8_t buffer[18];
59-
const byte len = 18;
69+
byte len = 18;
6070

6171
rfid.PCD_Authenticate(RC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(rfid.uid));
6272
rfid.MIFARE_Read(block, buffer, &len);
6373

6474
/*
65-
2 bytes - code size
66-
1 byte - parts [token]
67-
1 byte - full pages (including not full)
68-
1 byte - amount of data in last page
69-
1 byte - full blocks
70-
1 byte - amount of data in last block
75+
2 bytes - code size
76+
1 byte - parts [token]
77+
1 byte - full pages (including not full)
78+
1 byte - amount of data in last page
79+
1 byte - full blocks
80+
1 byte - amount of data in last block
7181
*/
7282
if (block == 1) {
7383
siz = word(buffer[0], buffer[1]);
@@ -117,18 +127,48 @@ void setup() {
117127
#endif
118128

119129
/* Write each page to flash */
120-
/* 3888 bytes free after removing serial */
121-
122-
130+
digitalWrite(A1, HIGH);
131+
boot_program_page(memptr, pageBuffer);
123132

124133
/* Finished writing to flash */
125-
memptr++;
134+
memptr += 256;
126135
memset(pageBuffer, 0xFF, 256);
127136
}
128137
rfid.PICC_HaltA();
129138
rfid.PCD_StopCrypto1(); // Stop encryption on PCD
139+
rfid.PCD_AntennaOff();
140+
141+
digitalWrite(A1, LOW);
142+
asm("jmp 0");
143+
}
144+
145+
void boot_program_page(uint32_t page, uint8_t *buf) {
146+
uint16_t i;
147+
uint8_t sreg;
148+
149+
sreg = SREG;
150+
cli();
151+
152+
eeprom_busy_wait();
153+
154+
boot_page_erase(page);
155+
boot_spm_busy_wait();
156+
for (i = 0; i < SPM_PAGESIZE; i += 2)
157+
{
158+
uint16_t w = *buf++;
159+
w += (*buf++) << 8;
160+
boot_page_fill(page + i, w);
161+
}
162+
163+
boot_page_write(page); // Store buffer in flash page.
164+
boot_spm_busy_wait(); // Wait until the memory is written.
165+
166+
// Reenable RWW-section again. We need this if we want to jump back
167+
// to the application after bootloading.
168+
boot_rww_enable();
130169

131-
asm("jmp 0x0000");
170+
// Re-enable interrupts (if they were ever enabled).
171+
SREG = sreg;
132172
}
133173

134174
void loop() {

MULoaderReader/RC522.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
11
#ifndef RC522_h
22
#define RC522_h
3-
#define __STDC_LIMIT_MACROS
4-
#include <stdint.h>
5-
#include <Arduino.h>
63
#include <SPI.h>
74
#ifndef RC522_SPICLOCK
85
#define RC522_SPICLOCK SPI_CLOCK_DIV4
96
#endif
107

118
class RC522 {
129
public:
13-
//static constexpr byte FIFO_SIZE = 64;
14-
//static constexpr uint8_t UNUSED_PIN = UINT8_MAX;
15-
1610
enum PCD_Register : byte {
1711
CommandReg = 0x01 << 1,
1812
ComIEnReg = 0x02 << 1,

MULoaderReader/platform.local.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
compiler.c.extra_flags=-Xlinker .text=0x7000
2+
compiler.c.elf.extra_flags=-Ttext 0x7000
3+
compiler.S.extra_flags=-Xlinker .text=0x7000
4+
compiler.cpp.extra_flags=-Xlinker .text=0x7000
5+
compiler.ar.extra_flags=
6+
compiler.objcopy.eep.extra_flags=
7+
compiler.elf2hex.extra_flags=

MULoaderWriter/MULoaderWriter.ino

Lines changed: 2 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -7,90 +7,11 @@ MFRC522 rfid(10, 9);
77
/*
88
YES, IT HAS TO BE THIS LONG
99
*/
10-
byte prog[] = {0x01, 0xE0, 0x07, 0x07, 0x08, 0xB9, 0xFE, 0xCF,
11-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
12-
13-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
14-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
15-
16-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
17-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
18-
19-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
20-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
21-
22-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
23-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
24-
25-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
26-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
27-
28-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
29-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
30-
31-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
32-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
33-
34-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
35-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
36-
37-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
38-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
39-
40-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
41-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
42-
43-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
44-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
45-
46-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
47-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
48-
49-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
50-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
51-
52-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
53-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
54-
55-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
56-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
57-
58-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
59-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
60-
61-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
62-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
63-
64-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
65-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
66-
67-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
68-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
69-
70-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
71-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
72-
73-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
74-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
75-
76-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
77-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
78-
79-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
80-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
81-
82-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
83-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
84-
85-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
86-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
87-
88-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
89-
0xDD, 0xDD, 0xDD, 0xDD, 0xDD
10+
byte prog[] = {0x01, 0xE0, 0x07, 0xB9, 0x08, 0xB9, 0xFE, 0xCF
9011
};
9112

9213
void setup() {
93-
Serial.begin(2000000);
14+
Serial.begin(115200);
9415
SPI.begin();
9516
rfid.PCD_Init();
9617
rfid.PCD_DumpVersionToSerial();

README.md

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ It's not end yet, block #0 is *NOT* meant for data storage, so all in all, inste
1818
During development I decided to take away one more block for sketch metadata (number of parts, code size etc) so we end up with 736 bytes of storage available per 1k tag (also it makes code a bit smaller, yay!).
1919
Luckily this is only for the first tag, the rest of tags will probably be able to store 752 bytes **(whole 16 bytes more)**.
2020

21-
Full 28672 byte code (in the worst case) will take up to 40 tags. Don't forget, that they will have to be scanned in specific order or your uC will crash at some point.
21+
Full 28672 byte code (in the worst case) will take up to 40 tags. Don't forget, that they will have to be scanned in specific order or your uC will crash at some point.
22+
I don't know why, but millis() is not working, but I cannot override them, because they're already defined ¯\_(ツ)_
2223

2324
Also, I didn't have any experience in working with AVR bootloaders nor RFID tags.
2425

@@ -34,6 +35,13 @@ N/A
3435
* MFRC522 reader from China (the working one)
3536
* Breadboard and some jumper wires
3637
* MIFARE Classic 1k tags (plenty of them)
38+
* External programmer (USBasp or AVRispmkII)
39+
40+
Fuse bits:
41+
* Low: 0xFF
42+
* High: 0xD8
43+
* Extended: FD
44+
* Lock: 3F
3745

3846
|Arduino|MFRC522|
3947
|-------|-------|
@@ -45,24 +53,27 @@ N/A
4553
| GND | GND |
4654
| 3V3 | 3V3 |
4755

48-
Reset circuit like this allowed to slim code a bit and as far as I see causes no problems so... It's working?
56+
Reset circuit like this allowed to slim code a bit and as far as I see causes no problems so... It's working?
57+
I added an LED on A1 to watch if flash is being updated.
58+
Test code lights up LED on A0.
4959

5060
### Software
5161
1. Compile whatever you want for Arduino
5262
2. Convert compiled code to C array
5363
3. Add this array to Writer source and upload to Arduino
5464
4. Scan tag and pray it transferred correctly (because there is no verification)
55-
5. Upload MULoaderReader to target
56-
6. Scan tag and watch stuff appearing in Serial Monitor
65+
5. Copy platform.local.txt to arduino/hardware/avr/[version] (remember to use it only with Reader)
66+
6. Upload MULoaderReader to target
67+
7. Scan tag and watch stuff appearing in Serial Monitor
5768

5869
Remember to uncomment define at the beginning of Reader code, otherwise you won't see anything :)
5970

6071
### What works
6172
* Uploading to tag (one)
6273
* Reading from tag
63-
* I know how to use SPM
74+
* Updating flash
6475

6576
### What doesn't work
6677
* Serial upload to tag (because I didn't implement it yet)
67-
* Bootloading uC with MULoaderReader (too big and stuff)
6878
* Programming tags in parts of 736 bytes
79+
* Bootloader timeout

Tests/blink.c

Lines changed: 0 additions & 13 deletions
This file was deleted.

Tests/light.hex

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:020000020000FC
2+
:0800000001E007B908B9FECFC9
3+
:00000001FF

0 commit comments

Comments
 (0)