Skip to content

Commit b18d3bb

Browse files
committed
Parts working!
Redesigned writing (16 bytes instead of whole page) Redesigned MFRC522 lib to be "pure-C compatible" (no Arduino headers needed) Restored code to get tag type Modified blink to light on A0 instead of D13 Moved ChipSelect as hard-coded in library Planning to move with this to Atmel Studio (this time for real) and get free from Arduino dependencies
1 parent 5aae1e2 commit b18d3bb

File tree

4 files changed

+352
-238
lines changed

4 files changed

+352
-238
lines changed

MULoaderReader/MULoaderReader.ino

Lines changed: 146 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
1-
#include <SPI.h>
2-
#include "RC522.h"
3-
#include <Arduino.h>
1+
#include <avr/io.h>
42
#include <avr/boot.h>
3+
#include "RC522.h"
4+
5+
/* Moving to Atmel Studio? */
56

6-
void __attribute__((noinline)) watchdogConfig(uint8_t x);
7+
void boot_program_page(uint32_t, uint8_t*);
8+
void __attribute__((noinline)) watchdogConfig(uint8_t);
9+
void initSPI();
710

8-
/* 3760 bytes free after removing serial */
9-
/* Compared with 5624 bytes it's a huge difference */
11+
/* 3820 bytes free after removing serial */
12+
/* Compared with 5714 bytes it's a huge difference */
1013
//#define S_DEBUG
1114

1215
void setup() {
1316
cli();
14-
pinMode(A1, OUTPUT);
15-
digitalWrite(A1, HIGH);
17+
DDRC |= 0b00000010;
18+
PORTC |= 0b00000010;
1619
#ifdef S_DEBUG
1720
Serial.begin(115200);
1821
Serial.println(F("MostUseless Bootloader Reader"));
@@ -31,7 +34,7 @@ void setup() {
3134
#endif
3235

3336
watchdogConfig(0);
34-
digitalWrite(A1, LOW);
37+
PORTC &= !0b00000010;
3538
asm("jmp 0");
3639
}
3740
}
@@ -40,150 +43,184 @@ void setup() {
4043
Serial.flush();
4144
#endif
4245

43-
SPI.begin();
44-
RC522 rfid(10);
46+
initSPI();
47+
RC522 rfid;
4548
rfid.PCD_Init();
4649

50+
/* Generic key */
51+
RC522::MIFARE_Key key;
52+
memset(key.keyuint8_t, 0xFF, 6);
53+
4754
/* You have 2 seconds to scan first tag */
48-
watchdogConfig((_BV(WDP2) | _BV(WDP1) | _BV(WDP0) | _BV(WDE)));
55+
watchdogConfig(_BV(WDP2) | _BV(WDP1) | _BV(WDP0) | _BV(WDE));
4956

50-
/* Jump to code after timeout */
51-
/* Timeout doesn't work but lol, the rest of stuff works */
57+
/* If the tag is not scanned, it will triger watchdog */
5258
while (!rfid.PICC_IsNewCardPresent());
5359
while (!rfid.PICC_ReadCardSerial());
5460

55-
digitalWrite(A1, LOW);
61+
/* Now you have 8 seconds between tags */
62+
watchdogConfig(_BV(WDP3) | _BV(WDP0) | _BV(WDE));
63+
64+
PORTC &= !0b00000010;
5665

5766
/* Sketch metadata */
5867
uint16_t siz = 0;
68+
uint16_t blocks = 0;
5969
uint8_t parts = 0;
60-
uint8_t pages = 0;
61-
uint8_t blocks = 2;
6270

63-
/* Buffer and SPM stuff */
64-
uint8_t pageoffset = 0;
65-
uint8_t memptr = 0;
71+
/* Programming */
72+
bool metaRead = false;
73+
uint8_t currentPart = 0;
74+
uint16_t blocksWritten = 0;
75+
volatile static uint8_t buffer[18];
76+
uint8_t len = 18;
6677

67-
/*
68-
We don't need to worry about extra data in last
69-
page if we already set buffer as empty :)
70-
*/
71-
volatile static uint8_t pageBuffer[256];
72-
memset(pageBuffer, 0xFF, 256);
78+
/* Buffer and SPM stuff */
79+
volatile static uint8_t writeBuffer[16];
80+
uint16_t memptr = 0;
81+
82+
/* Token capacity (blocks) may vary */
83+
uint16_t tokencap = 0;
84+
do {
85+
PORTC |= 0b00000010;
86+
asm("wdr");
87+
#ifdef S_DEBUG
88+
Serial.println("Scan tag");
89+
Serial.flush();
90+
#endif
91+
/* Check new card */
92+
while (!rfid.PICC_IsNewCardPresent());
93+
while (!rfid.PICC_ReadCardSerial());
94+
RC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
95+
PORTC &= !0b00000010;
96+
97+
switch (piccType) {
98+
case RC522::PICC_TYPE_MIFARE_UL:
99+
case RC522::PICC_TYPE_MIFARE_PLUS:
100+
case RC522::PICC_TYPE_MIFARE_DESFIRE:
101+
case RC522::PICC_TYPE_MIFARE_4K:
102+
case RC522::PICC_TYPE_MIFARE_MINI: //I dare you to use this one
103+
tokencap = 0;
104+
default: continue;
105+
case RC522::PICC_TYPE_MIFARE_1K:
106+
tokencap = 64; break;
107+
}
73108

74-
/* Generic key */
75-
RC522::MIFARE_Key key;
76-
memset(key.keyByte, 0xFF, 6);
109+
if (tokencap == 0) {
110+
#ifdef S_DEBUG
111+
Serial.println("Not supported");
112+
#endif
113+
return;
114+
}
77115

78-
/*
79-
Reading every block and using page offset
80-
to save progress if more parts are needed
81-
*/
116+
rfid.PCD_Authenticate(RC522::PICC_CMD_MF_AUTH_KEY_A, 1, &key, &(rfid.uid));
117+
rfid.MIFARE_Read(1, buffer, &len);
82118

83-
for (uint8_t block = 1; block < blocks; block++) {
84-
if ((block + 1) % 4 == 0) {
85-
blocks++;
119+
if (buffer[0] - 1 != currentPart) {
120+
#ifdef S_DEBUG
121+
Serial.print("Wrong part: ");
122+
Serial.print(buffer[0]);
123+
Serial.print(" != ");
124+
Serial.println(currentPart + 1);
125+
#endif
126+
rfid.PICC_HaltA();
127+
rfid.PCD_StopCrypto1();
86128
continue;
87129
}
88130

89-
uint8_t buffer[18];
90-
byte len = 18;
91-
92-
rfid.PCD_Authenticate(RC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(rfid.uid));
93-
rfid.MIFARE_Read(block, buffer, &len);
94-
95-
/*
96-
2 bytes - code size
97-
1 byte - parts [token]
98-
1 byte - full pages (including not full)
99-
1 byte - amount of data in last page
100-
1 byte - full blocks
101-
1 byte - amount of data in last block
102-
*/
103-
if (block == 1) {
131+
if (!metaRead && currentPart == 0) {
132+
/*
133+
2 bytes - code size
134+
2 bytes - full blocks
135+
1 byte - pages (unused)
136+
1 byte - parts [tokens]
137+
*/
104138
siz = word(buffer[1], buffer[2]);
105-
blocks = word(buffer[3], buffer[4]) + 2;
106-
pages = buffer[5];
139+
blocks = word(buffer[3], buffer[4]);
107140
parts = buffer[6];
108141
#ifdef S_DEBUG
109142
Serial.print(F("Sketch size:\t"));
110143
Serial.print(siz);
111144
Serial.print(F(" bytes\r\nParts [tokens]:\t"));
112145
Serial.println(parts);
113-
Serial.print(F("Pages total:\t"));
114-
Serial.println(pages);
115146
Serial.print(F("Blocks total:\t"));
116-
Serial.println(blocks - 2);
147+
Serial.println(blocks);
117148
Serial.flush();
118149
#endif
119-
continue;
150+
metaRead = true;
120151
}
121152

122-
for (uint8_t a = 0; a < 16; a++) {
123-
pageBuffer[(pageoffset * 16) + a] = buffer[a];
153+
for (uint8_t a = 2;
154+
a < tokencap && blocksWritten != blocks;
155+
a++) {
156+
asm("wdr");
157+
if ((a + 1) % 4 == 0) continue;
158+
#ifdef S_DEBUG
159+
Serial.print(a);
160+
Serial.print('\t');
161+
#endif
162+
rfid.PCD_Authenticate(RC522::PICC_CMD_MF_AUTH_KEY_A, a, &key, &(rfid.uid));
163+
rfid.MIFARE_Read(a, buffer, &len);
164+
for (uint16_t x = 0; x < 16; x++)
165+
writeBuffer[x] = buffer[x];
166+
167+
PORTC |= 0b00000010;
168+
boot_program_page(memptr, writeBuffer);
169+
blocksWritten += 1;
170+
memptr += 16;
124171
}
125-
pageoffset++;
126172

127-
/* Check if page is full */
128-
if (pageoffset < 16 && block != blocks - 1) continue;
129-
pageoffset = 0;
173+
rfid.PICC_HaltA();
174+
rfid.PCD_StopCrypto1();
130175

176+
currentPart += 1;
177+
} while (currentPart <= parts && blocksWritten != blocks);
178+
PORTC |= 0b00000010;
131179
#ifdef S_DEBUG
132-
Serial.print(F("\r\n ---- Page "));
133-
Serial.print(memptr + 1);
134-
Serial.println(F(" ----"));
135-
for (uint16_t x = 1; x <= 256; x++) {
136-
Serial.print(pageBuffer[x - 1] < 0x10 ? " 0" : " ");
137-
Serial.print(pageBuffer[x - 1], HEX);
138-
if (x % 16 == 0)
139-
Serial.println();
140-
}
141-
Serial.flush();
180+
Serial.println("Done!");
181+
Serial.flush();
142182
#endif
143183

144-
/* Write each page to flash */
145-
digitalWrite(A1, HIGH);
146-
boot_program_page(memptr, pageBuffer);
147-
148-
/* Finished writing to flash */
149-
memptr += 256;
150-
memset(pageBuffer, 0xFF, 256);
151-
}
152-
rfid.PICC_HaltA();
153-
rfid.PCD_StopCrypto1(); // Stop encryption on PCD
184+
/* We're done here */
154185
rfid.PCD_AntennaOff();
155-
156-
digitalWrite(A1, LOW);
157186
watchdogConfig(_BV(WDE)); //16ms
187+
PORTC &= !0b00000010;
158188
while (1); //Trigger watchdog to jump to code
159189
}
160190

161-
void boot_program_page(uint32_t page, uint8_t *buf) {
162-
uint16_t i;
191+
void boot_program_page(uint16_t addr, uint8_t *buf) {
192+
#ifdef S_DEBUG
193+
Serial.print("Writing at: ");
194+
Serial.println(addr);
195+
Serial.print('\t');
196+
for (uint16_t x = 0; x < 16; x++) {
197+
Serial.print(buf[x] < 0x10 ? " 0" : " ");
198+
Serial.print(buf[x], HEX);
199+
}
200+
Serial.println();
201+
Serial.flush();
202+
#endif
163203
uint8_t sreg;
164204

165205
sreg = SREG;
166206
cli();
167207

168208
eeprom_busy_wait();
169209

170-
boot_page_erase(page);
210+
if (addr == 0 || addr % SPM_PAGESIZE == 0)
211+
boot_page_erase(addr);
171212
boot_spm_busy_wait();
172-
for (i = 0; i < SPM_PAGESIZE; i += 2)
213+
for (uint8_t i = 0; i < 16; i += 2)
173214
{
174215
uint16_t w = *buf++;
175216
w += (*buf++) << 8;
176-
boot_page_fill(page + i, w);
217+
boot_page_fill(addr + i, w);
177218
}
178219

179-
boot_page_write(page); // Store buffer in flash page.
180-
boot_spm_busy_wait(); // Wait until the memory is written.
181-
182-
// Reenable RWW-section again. We need this if we want to jump back
183-
// to the application after bootloading.
220+
boot_page_write(addr);
221+
boot_spm_busy_wait();
184222
boot_rww_enable();
185223

186-
// Re-enable interrupts (if they were ever enabled).
187224
SREG = sreg;
188225
}
189226

@@ -192,5 +229,18 @@ void watchdogConfig(uint8_t x) {
192229
WDTCSR = x;
193230
}
194231

232+
void initSPI() {
233+
uint8_t sreg = SREG;
234+
cli();
235+
236+
/* Set up SPI outs */
237+
DDRB |= 0b101100;
238+
/* SPI in */
239+
DDRB &= 0b101111;
240+
241+
SPCR |= _BV(MSTR) | _BV(SPE);
242+
SREG = sreg;
243+
}
244+
195245
void loop() {
196246
}

0 commit comments

Comments
 (0)