diff options
author | Linus Nordberg <linus@nordberg.se> | 2016-06-10 16:07:27 +0200 |
---|---|---|
committer | Linus Nordberg <linus@nordberg.se> | 2016-06-10 16:07:27 +0200 |
commit | 54cd4de78da2534b61c26a7f07abf45907e582d0 (patch) | |
tree | dc25868bdbf7cdfc7dcdf98b65f12667d381503d | |
parent | 4f229e0b1083154ee033ca9c2fd5c5367e1621ae (diff) |
Do wipe MKM when tamper is detected, sleep when not.
Writing the MKM in "sequential mode" (a.k.a. "burst") but still
busy-waiting for confirmation of SPI write operation being done.
Would using an interrupt be faster?
Sleeping is done in "power down mode". There are less sleepy modes
which presumably consume more power but might wake up quicker. A good
start would be to figure out how long time it takes to wake up from
power down.
-rw-r--r-- | tamper.c | 142 |
1 files changed, 84 insertions, 58 deletions
@@ -5,12 +5,6 @@ #include <avr/io.h> /* -D__AVR_ATtiny828__ will include <avr/iotn828.h> */ /* Mapping of pins to names. */ -#define AVR_LED1 PORTA0 -#define AVR_LED2 PORTA3 -#define AVR_LED3 PORTA2 -#define AVR_LED4 PORTA1 -#define AVR_PANIC PORTA4 - #define MKM_AVR_CS_N PORTA5 #define MKM_CONTROL_AVR_ENA PORTA6 #define MKM_CONTROL_FPGA_DIS PORTA7 @@ -19,7 +13,6 @@ #define MKM_AVR_MISO PORTD1 #define MKM_AVR_SCK PORTD3 - /* Input pins. */ #define AVR_PANIC_PIN PINA /* Panic button. */ #define AVR_PANIC_BIT PINA4 /* 0 = panic. */ @@ -32,13 +25,13 @@ #define AVR_LED_GREEN_BIT PORTA1 #define MKM_CS_PORT PORTA /* MKM chip select. */ -#define MKM_CS_BIT MKM_AVR_CS_N /* 0 -> selected. */ +#define MKM_CS_BIT MKM_AVR_CS_N /* 0 => selected. */ #define MKM_CONTROL_AVR_PORT PORTA /* AVR in control. */ -#define MKM_CONTROL_AVR_BIT MKM_CONTROL_AVR_ENA /* 0 -> in control. */ +#define MKM_CONTROL_AVR_BIT MKM_CONTROL_AVR_ENA /* 0 => in control. */ #define MKM_CONTROL_FPGA_PORT PORTA /* FPGA in control. */ -#define MKM_CONTROL_FPGA_BIT MKM_CONTROL_FPGA_DIS /* 0 -> in control. */ +#define MKM_CONTROL_FPGA_BIT MKM_CONTROL_FPGA_DIS /* 0 => in control. */ /* SPI. */ #define MKM_AVR_MOSI_PORT PORTD @@ -85,11 +78,11 @@ spi_setup(int on_flag) /* Disable SPI power reduction. */ PRR &= ~_BV(PRSPI); - /* Set MOSI and SCK to output. */ + /* Configure MOSI and SCK pins as output. */ DDRD = _BV(MKM_AVR_MOSI_BIT) | _BV(MKM_AVR_SCK_BIT); - /* Make sure SPI slave select (SS) is configured as output before - enabling SPI master mode!. */ + /* Make sure SPI slave select (SS) is configured as output + before enabling SPI master mode! */ DDRC |= _BV(SPI_SS); /* Enable SPI in master mode, clock rate f/16. */ @@ -97,8 +90,8 @@ spi_setup(int on_flag) } else { - SPCR &= ~_BV(SPE); - PRR |= _BV(PRSPI); + SPCR &= ~_BV(SPE); /* Disable SPI. */ + PRR |= _BV(PRSPI); /* Enable SPI power reduction. */ } } @@ -138,27 +131,18 @@ spi_read_status() return SPDR; } -static inline void -spi_set_operation_byte() -{ - spi_write(SPI_WRSR); - spi_write(0x00); -} +#define SPI_OPERATION_BYTE 0x00 +#define SPI_OPERATION_SEQUENCE 0x40 +#define SPI_OPERATION_PAGE 0x80 static inline void -spi_set_operation_page() +spi_set_operation(uint8_t mode) { spi_write(SPI_WRSR); - spi_write(0x80); -} - -static inline void -spi_set_operation_seq() -{ - spi_write(SPI_WRSR); - spi_write(0x40); + spi_write(mode); } +#if 0 static void spi_write_byte(uint16_t addr, uint8_t data) { @@ -181,6 +165,17 @@ spi_read_byte(uint16_t addr) mkm_chip_select(0); return data; } +#endif + +/**********************/ +/* Tamper protection. */ +#if 0 +/* Interrupt handler for tamper pin. */ +void +tamper_int(void) __attribute__ ((interrupt)) +{ +} +#endif static inline int panic_p() @@ -188,49 +183,80 @@ panic_p() return !bit_is_set(AVR_PANIC_PIN, AVR_PANIC_BIT); } - static inline void init_ports() { - /* Configure all PORTA pins except the tamper detection pin to + /* Configure all PORTA pins except the tamper detection pin as outputs. */ DDRA = 0xff & ~_BV(AVR_PANIC_BIT); } +static void +init_interrupts() +{ + PCMSK0 |= _BV(PCINT4); /* Set mask bit for PCINT4 */ + PCICR |= _BV(PCIE0); /* Enable pin change interrupt 0. */ +} + +static void +init_power_reduction() +{ + /* TBD: Disable everything that we don't need? Note that the effect + of this should marginal since it's only saving energy when we're + awaken and actualy wiping memory. */ +} + +static inline void +mkm_wipe() +{ + AVR_LED_PORT |= _BV(AVR_LED_RED_BIT); + + spi_setup(1); + mkm_grab(); + mkm_chip_select(1); + spi_set_operation(SPI_OPERATION_SEQUENCE); + spi_write(SPI_WRITE); + spi_write(0); /* Address, high byte. */ + spi_write(0); /* Address, low byte. */ + for (int i = 0; i < 0x1fff; i++) /* 8192 bytes (64Kbit). */ + spi_write(0); + mkm_chip_select(0); + mkm_release(); + spi_setup(0); + + AVR_LED_PORT &= ~_BV(AVR_LED_RED_BIT); +} + +static inline void +sleep() +{ + SMCR &= ~0x2; /* Set sleep mode to "power down"... */ + SMCR |= 0x5; /* ... and enable sleep. */ + asm("sei"); /* Enable interrupts. */ + asm("sleep"); /* Go to sleep. */ + + SMCR &= ~0x1; /* Disable sleep. */ +} + int main() { init_ports(); + init_power_reduction(); + init_interrupts(); + + /* Flash LED's at startup. */ + AVR_LED_PORT |= 0x0f; + for (int i = 0; i < 16000; i++); + AVR_LED_PORT &= ~0x0f; - int i, j = 0, wait; - uint8_t mkm_val = 0; while (1) { if (panic_p()) - { - spi_setup(1); - mkm_grab(); - - spi_write_byte(0, spi_read_byte(0) + 1); - mkm_val = spi_read_byte(0); - AVR_LED_PORT = (AVR_LED_PORT & 0xf0) | (mkm_val & 0x0f); - - wait = 32000; - } - else - { - mkm_release(); - spi_setup(0); - - if ((j++ & 1) == 0) - AVR_LED_PORT = (AVR_LED_PORT & 0xf0) | 0xa; - else - AVR_LED_PORT = (AVR_LED_PORT & 0xf0) | 0x5; - - wait = 16000; - } - - for (i = 0; i < wait; i++); + mkm_wipe(); + + if (!panic_p()) + sleep(); } return 0; |