mirror of
https://codeberg.org/SiB64/turbo_weather.git
synced 2026-05-01 15:14:22 +02:00
Compare commits
2 commits
46809f6fac
...
97d00bc908
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97d00bc908 | ||
|
|
90aaf8d48e |
12 changed files with 474 additions and 148 deletions
|
|
@ -8,7 +8,7 @@ all: $(PROJ).hex
|
|||
|
||||
SN_dose = 1
|
||||
MCU_dose = attiny424
|
||||
C_FILES_dose = config.c cmd.c pwm.c uart.c base85.c bch4369.c rtc.c spi.c flash.c adc.c
|
||||
C_FILES_dose = config.c cmd.c pipe.c pwm.c uart.c base85.c bch4369.c rtc.c spi.c flash.c adc.c
|
||||
S_FILES_dose = uart_tx.S base85a.S
|
||||
|
||||
MCU = $(MCU_$(PROJ))
|
||||
|
|
|
|||
|
|
@ -49,9 +49,16 @@ void bch4369(uint8_t d)
|
|||
}
|
||||
}
|
||||
|
||||
void bch4369_str(uint8_t *b, uint8_t n)
|
||||
{
|
||||
do
|
||||
bch4369(*b++);
|
||||
while (--n);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
__attribute__ ((noinline, noclone))
|
||||
__attribute__ ((noinline, naked))
|
||||
void bch4369(uint8_t d)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
|
|
@ -65,7 +72,7 @@ void bch4369(uint8_t d)
|
|||
"adiw r30, 16" "\n\t"
|
||||
"ldi r26, lo8(bch_genpoly+16)" "\n\t"
|
||||
"ldi r27, hi8(bch_genpoly+16)" "\n\t"
|
||||
"rol %[D]" "\n\t" // move next input bit → r25.7
|
||||
"rol r24" "\n\t" // move next input bit → r25.7
|
||||
"ror r25" "\n\t"
|
||||
"2:" "\n\t"
|
||||
"rol r25" "\n\t" // Move r25.7 → C-bit
|
||||
|
|
@ -81,12 +88,26 @@ void bch4369(uint8_t d)
|
|||
"brne 2b" "\n\t"
|
||||
"bst r25, 6" "\n\t" // copy MSB r25.6 → T-bit
|
||||
"subi r20, 1" "\n\t"
|
||||
"brne 1b" "\n"
|
||||
: [D] "+w" (d)
|
||||
:
|
||||
: "memory", "cc",
|
||||
"r0", "r20", "r21", "r25",
|
||||
"r26", "r27", "r30", "r31"
|
||||
"brne 1b" "\n\t"
|
||||
"ret" "\n"
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__ ((noinline, naked))
|
||||
void bch4369_str(const uint8_t *b, uint8_t n)
|
||||
{
|
||||
// _bch4369 preserves r22, r23, r18, r19
|
||||
__asm__ __volatile__ (
|
||||
""
|
||||
"movw r18, r28" "\n\t"
|
||||
"movw r28, r24" "\n"
|
||||
"1:" "\n\t"
|
||||
"ld r24, Y+" "\n\t"
|
||||
"rcall bch4369" "\n\t"
|
||||
"subi r22, 1" "\n\t"
|
||||
"brne 1b" "\n\t"
|
||||
"mov r28, r18" "\n\t"
|
||||
"ret" "\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,3 +4,4 @@
|
|||
extern uint8_t bch_parity[16];
|
||||
void bch4369(uint8_t d);
|
||||
static inline void bch4369_init() { memset(bch_parity, 0 , 16); }
|
||||
void bch4369_str(const uint8_t *b, uint8_t n);
|
||||
|
|
|
|||
226
src/cmd.c
226
src/cmd.c
|
|
@ -8,85 +8,14 @@
|
|||
#include "bch4369.h"
|
||||
#include "base85.h"
|
||||
#include "uart.h"
|
||||
#include "pipe.h"
|
||||
|
||||
void base85_send_buffer(const uint8_t *buf);
|
||||
const uint8_t *base85_fill_buffer(const uint8_t *s);
|
||||
const uint8_t *skip_space(const uint8_t *s);
|
||||
uint8_t cmd_buffer[16];
|
||||
uint8_t uart_stream_source;
|
||||
|
||||
void parse_command(const uint8_t *s, uint8_t n)
|
||||
{
|
||||
uint8_t cmd = *s++;
|
||||
if (*s =='|')
|
||||
return;
|
||||
s = skip_space(s);
|
||||
uint8_t flag = *s++;
|
||||
uint8_t r = 0;
|
||||
send_char(cmd);
|
||||
send_char('|');
|
||||
if (cmd == 'A') {
|
||||
r = adc_current;
|
||||
if (r >= N_ADC) {
|
||||
if (flag == '>') {
|
||||
base85_send_buffer((void*)adc_readings);
|
||||
flag = *s++;
|
||||
}
|
||||
if (flag == '+')
|
||||
start_adc();
|
||||
}
|
||||
}
|
||||
if (cmd == 'W') {
|
||||
s = base85_fill_buffer(s);
|
||||
r = base85_error;
|
||||
}
|
||||
else if (cmd == 'B') {
|
||||
if (flag == '<') {
|
||||
s = base85_fill_buffer(s);
|
||||
flag = *s - '0';
|
||||
if (flag < 4) {
|
||||
s++;
|
||||
if (!(uart_stream_source & 0xe0)) {
|
||||
memcpy(flash_buffer+16*flag, cmd_buffer, 16);
|
||||
uart_stream_source = flag;
|
||||
}
|
||||
r = uart_stream_source;
|
||||
}
|
||||
flag = *s++;
|
||||
}
|
||||
r = base85_error;
|
||||
if (!r && flag == '%') {
|
||||
if (*s=='>')
|
||||
base85_send_buffer(bch_parity);
|
||||
else if (*s=='<')
|
||||
bch4369_feed_buffer(*++s);
|
||||
r = bch4369_feed_n;
|
||||
}
|
||||
else if (flag == '>') {
|
||||
uint8_t *b = cmd_buffer;
|
||||
flag = *s - '0';
|
||||
if (flag < 4)
|
||||
b = flash_buffer + 16*flag;
|
||||
base85_send_buffer(b);
|
||||
}
|
||||
}
|
||||
else if (cmd=='F') {
|
||||
base85_fill_buffer(s);
|
||||
r = base85_error;
|
||||
if (!r)
|
||||
r = flash_submit_command(cmd_buffer);
|
||||
}
|
||||
else
|
||||
send_char('?');
|
||||
send_hex_byte_eol(r);
|
||||
}
|
||||
|
||||
const uint8_t *skip_space(const uint8_t *s) {
|
||||
while (*s == ' ')
|
||||
s++;
|
||||
return s;
|
||||
}
|
||||
uint8_t cmd_buffer_valid;
|
||||
|
||||
static inline
|
||||
const uint8_t *base85_fill_buffer(const uint8_t *s) {
|
||||
base85_error = 0;
|
||||
s = skip_space(s);
|
||||
|
|
@ -96,6 +25,151 @@ const uint8_t *base85_fill_buffer(const uint8_t *s) {
|
|||
return s;
|
||||
}
|
||||
|
||||
uint8_t * poke_addr;
|
||||
uint8_t peek_size;
|
||||
struct peak_poke {
|
||||
uint8_t *addr;
|
||||
uint8_t size;
|
||||
uint8_t ccp;
|
||||
uint8_t data[12];
|
||||
};
|
||||
|
||||
static inline
|
||||
uint8_t poke(struct peak_poke *p, uint8_t hp, uint8_t poke)
|
||||
{
|
||||
if (hp) {
|
||||
poke_addr = p->addr;
|
||||
peek_size = p->size;
|
||||
}
|
||||
else {
|
||||
p->addr = poke_addr;
|
||||
p->size = peek_size;
|
||||
}
|
||||
uint8_t s = peek_size;
|
||||
uint8_t *a = poke_addr;
|
||||
if (s > 12)
|
||||
s = 12;
|
||||
peek_size -= s;
|
||||
poke_addr += s;
|
||||
if (poke) {
|
||||
if (p->ccp)
|
||||
NVMCTRL.CTRLA = NVMCTRL_CMD_PAGEBUFCLR_gc;
|
||||
memcpy(a, p->data, s);
|
||||
if (p->ccp && !(0x8000 & (uint16_t)a))
|
||||
__asm__(
|
||||
"out %[ccp], %[key] \n\t"
|
||||
"sts %[ctrla], %[cmd] \n"
|
||||
:: [ccp] "n" (&CCP),
|
||||
[ctrla] "n" (&NVMCTRL.CTRLA),
|
||||
[key] "r" (p->ccp),
|
||||
[cmd] "r" (NVMCTRL_CMD_PAGEERASEWRITE_gc)
|
||||
: "memory", "r0"
|
||||
);
|
||||
}
|
||||
else
|
||||
memcpy(p->data, a, s);
|
||||
return s && !poke;
|
||||
}
|
||||
|
||||
void parse_command(const uint8_t *s, uint8_t n)
|
||||
{
|
||||
uint8_t cmd = *s++;
|
||||
if (*s =='`')
|
||||
return;
|
||||
uint8_t r = 0x08|cmd;
|
||||
send_char('`');
|
||||
send_char(cmd);
|
||||
uint8_t have_b = !(cmd & 0x20);
|
||||
cmd |= 0x20;
|
||||
if (cmd > 'z')
|
||||
goto error;
|
||||
if (have_b) {
|
||||
s = base85_fill_buffer(s);
|
||||
if (base85_error) {
|
||||
r = base85_error;
|
||||
goto error;
|
||||
}
|
||||
cmd_buffer_valid |= 0x80;
|
||||
}
|
||||
s = skip_space(s);
|
||||
uint8_t flag = *s++;
|
||||
switch(cmd) {
|
||||
case 'a':
|
||||
r = adc_current;
|
||||
if (r >= N_ADC) {
|
||||
if (flag=='=') {
|
||||
memcpy(cmd_buffer, adc_readings, 16);
|
||||
cmd_buffer_valid |= 0x40;
|
||||
flag = *s++;
|
||||
}
|
||||
if (flag == '<') {
|
||||
base85_send_buffer((void*)adc_readings);
|
||||
flag = *s++;
|
||||
}
|
||||
if (flag == '+')
|
||||
start_adc();
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
r = cmd_buffer_valid;
|
||||
if (have_b) {
|
||||
flag -= '0';
|
||||
if (flag < 5 && flag==cmd_buffer_valid) {
|
||||
memcpy(flash_buffer+16*flag, cmd_buffer, 16);
|
||||
r = cmd_buffer_valid |= 1<<flag;
|
||||
flag = *++s;
|
||||
}
|
||||
}
|
||||
if (flag == '%') {
|
||||
if (*s=='<')
|
||||
base85_send_buffer(bch_parity);
|
||||
if (have_b)
|
||||
bch4369_feed_buffer(*++s);
|
||||
r = bch4369_feed_n;
|
||||
}
|
||||
else if (flag == '<') {
|
||||
flag = *s - '0';
|
||||
uint8_t *b;
|
||||
if (flag < 5)
|
||||
b = flash_buffer + 16*flag;
|
||||
else {
|
||||
b = cmd_buffer;
|
||||
}
|
||||
base85_send_buffer(b);
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
if (have_b) {
|
||||
r = flash_submit_command(cmd_buffer);
|
||||
cmd_buffer_valid &=~ 0x80;
|
||||
}
|
||||
else
|
||||
r = flash_poll(flag=='!');
|
||||
break;
|
||||
case 'p':
|
||||
if (have_b) {
|
||||
r = pipe_config(cmd_buffer, flag);
|
||||
cmd_buffer_valid &= ~0x80;
|
||||
}
|
||||
else
|
||||
r = pipe_poll(flag=='!');
|
||||
break;
|
||||
case 'm':
|
||||
if (poke((void*)cmd_buffer, have_b, have_b && flag=='!'))
|
||||
base85_send_buffer(cmd_buffer);
|
||||
default:
|
||||
error:
|
||||
send_char('?');
|
||||
}
|
||||
send_hex_byte_eol(r);
|
||||
}
|
||||
|
||||
const uint8_t *skip_space(const uint8_t *s) {
|
||||
while (*s == ' ')
|
||||
s++;
|
||||
return s;
|
||||
}
|
||||
|
||||
void base85_send_buffer(const uint8_t *buf)
|
||||
{
|
||||
uint8_t s[6];
|
||||
|
|
@ -113,7 +187,7 @@ void bch4369_feed_buffer(uint8_t flag)
|
|||
bch4369_feed_n = 0;
|
||||
memset(bch_parity, 0, 16);
|
||||
}
|
||||
for (int i=0; i<16; i++)
|
||||
bch4369(cmd_buffer[i]);
|
||||
bch4369_str(cmd_buffer,16);
|
||||
bch4369_feed_n++;
|
||||
}
|
||||
|
||||
|
|
|
|||
25
src/config.c
25
src/config.c
|
|
@ -1,5 +1,30 @@
|
|||
|
||||
#include "config.h"
|
||||
#include "flash.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Configuration in USERROW
|
||||
|
||||
__attribute__((section(".userrow")))
|
||||
const struct config config = {
|
||||
.magic = USE_USERROW,
|
||||
.version = USE_VERSION,
|
||||
.cpu_clk = CLKCTRL_PDIV_2X_gc | 1, // 10MHz (max @ 3V)
|
||||
.flash_page_size = FM_528 >> 8,
|
||||
.burn_page = 0x88, // Buffer 1 Page Program w/o Erase
|
||||
.write_buffer = 0x84 | FM_WRITE>>8, // Buffer 1 Write
|
||||
.read_array = 0x03 | FM_READ>>8, // Continuous Array Read (Low-Frequency)
|
||||
.read_buffer = {
|
||||
[0] = 0xd1 | FM_READ>>8, // Buffer 1 Read (Low-Frequency)
|
||||
[1] = 0xd3 | FM_READ>>8, // Buffer 2 Read (Low-Frequency)
|
||||
},
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Configuration in EEPROM
|
||||
|
||||
|
||||
struct_ioconf(port_config) = {
|
||||
conf_prefix(PORTA),
|
||||
|
|
|
|||
23
src/config.h
23
src/config.h
|
|
@ -4,6 +4,29 @@
|
|||
#include <avr/io.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// USERROW
|
||||
|
||||
struct config {
|
||||
uint8_t magic;
|
||||
uint8_t version;
|
||||
uint8_t cpu_clk;
|
||||
uint8_t flash_page_size;
|
||||
uint16_t burn_page;
|
||||
uint16_t erase_page;
|
||||
uint16_t write_buffer;
|
||||
uint16_t read_array;
|
||||
uint16_t read_buffer[2];
|
||||
};
|
||||
|
||||
enum magic_flags {
|
||||
USE_USERROW = 0xD0,
|
||||
USE_VERSION = 0x01,
|
||||
};
|
||||
|
||||
extern const struct config config;
|
||||
|
||||
// EEPROM
|
||||
|
||||
struct io_config {
|
||||
uint8_t addr;
|
||||
uint8_t val;
|
||||
|
|
|
|||
12
src/dose.c
12
src/dose.c
|
|
@ -21,18 +21,6 @@
|
|||
#include "pwm.h"
|
||||
#include "flash.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Configuration in USERROW
|
||||
|
||||
__attribute__((section(".userrow")))
|
||||
const struct config config = {
|
||||
.magic = USE_USERROW,
|
||||
.version = USE_VERSION,
|
||||
.cpu_clk = CLKCTRL_PDIV_2X_gc | 1, // 10MHz (max @ 3V)
|
||||
.flash_page_size = FM_528,
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// main()
|
||||
|
|
|
|||
14
src/dose.h
14
src/dose.h
|
|
@ -9,17 +9,3 @@
|
|||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
|
||||
struct config {
|
||||
uint8_t magic;
|
||||
uint8_t version;
|
||||
uint8_t cpu_clk;
|
||||
uint8_t flash_page_size;
|
||||
};
|
||||
|
||||
enum magic_flags {
|
||||
USE_USERROW = 0xD0,
|
||||
USE_VERSION = 0x01,
|
||||
|
||||
};
|
||||
|
||||
extern const struct config config;
|
||||
|
|
|
|||
252
src/flash.c
252
src/flash.c
|
|
@ -82,8 +82,10 @@ miscellanious
|
|||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "flash.h"
|
||||
#include "cmd.h"
|
||||
#include "bch4369.h"
|
||||
|
||||
uint8_t flash_cmd_buffer[4];
|
||||
uint8_t flash_status_bytes[2];
|
||||
|
|
@ -98,7 +100,6 @@ uint8_t flash_cmd(uint16_t mode, uint16_t what, uint16_t page, uint16_t byte)
|
|||
{
|
||||
uint8_t spi_mode = SPI_FLASH | mode & FM_SPI;
|
||||
uint8_t op = mode;
|
||||
mode >>= 8;
|
||||
uint8_t size = what;
|
||||
what >>= 8;
|
||||
uint8_t s = spi_select(spi_mode);
|
||||
|
|
@ -124,11 +125,16 @@ uint8_t flash_cmd(uint16_t mode, uint16_t what, uint16_t page, uint16_t byte)
|
|||
case FM_PAD2: pads += 1;
|
||||
case FM_PAD1: pads += 1;
|
||||
}
|
||||
if (size >= 128) {
|
||||
// for read of the security register
|
||||
pads += size-64;
|
||||
size = 64;
|
||||
}
|
||||
spi.zsize = pads;
|
||||
if (what + size <= 64)
|
||||
if (what + size <= 80)
|
||||
b = flash_buffer + what;
|
||||
else if (what+size <= 80)
|
||||
b = cmd_buffer + (what-64);
|
||||
else if (what>=96 && what+size <= 112)
|
||||
b = cmd_buffer + (what-96);
|
||||
else if (size <= 2)
|
||||
b = flash_status_bytes;
|
||||
else
|
||||
|
|
@ -148,58 +154,6 @@ uint8_t flash_cmd(uint16_t mode, uint16_t what, uint16_t page, uint16_t byte)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint16_t flash_page, flash_block, n_blocks;
|
||||
uint8_t flash_stream_status;
|
||||
|
||||
enum {
|
||||
FS_IDLE = 0,
|
||||
FS_Rdy = 1,
|
||||
FS_Bsy = 2,
|
||||
FS_Read = 4,
|
||||
FS_Write = 8,
|
||||
FS_Erase = 12,
|
||||
FS_Buff = 32,
|
||||
FS_StBsy = 64,
|
||||
FS_TxBCH = 128,
|
||||
};
|
||||
|
||||
uint8_t flash_poll()
|
||||
{
|
||||
uint8_t r = spi_busy_p();
|
||||
if (r)
|
||||
// SPI is shifting something
|
||||
return 0x80 | r;
|
||||
r = flash_stream_status;
|
||||
if (r & FS_StBsy) {
|
||||
// status bytes arrived
|
||||
if (flash_status_bytes[0] & 0x80)
|
||||
// flash is still busy burning
|
||||
goto rd_status;
|
||||
// not busy any more, move Bsy → Rdy
|
||||
if (r & FS_Bsy)
|
||||
r |= FS_Rdy;
|
||||
goto rdy;
|
||||
}
|
||||
if (!(r & FS_Bsy))
|
||||
goto rdy;
|
||||
if (r & FS_Write) {
|
||||
rd_status:
|
||||
// request status bytes for pending Tx od Er
|
||||
r |= FS_StBsy;
|
||||
flash_stream_status = r;
|
||||
flash_cmd_na(0xd7, 0xff02);
|
||||
return r & FS_Bsy;
|
||||
}
|
||||
// Rx is Rdy when SPI is idle
|
||||
rdy:
|
||||
// clear the Bsy bits
|
||||
r &= ~(FS_Bsy | FS_StBsy);
|
||||
// return the ready bits
|
||||
flash_stream_status = r;
|
||||
return r;
|
||||
}
|
||||
|
||||
struct flash_cmd {
|
||||
uint16_t mode, what, page, byte;
|
||||
uint8_t buffer[8];
|
||||
|
|
@ -210,3 +164,189 @@ uint8_t flash_submit_command(uint8_t *cmd)
|
|||
struct flash_cmd *c = (void*)cmd;
|
||||
return flash_cmd(c->mode, c->what, c->page, c->byte);
|
||||
}
|
||||
struct flash_stream fs;
|
||||
|
||||
__attribute__ ((noinline, noclone))
|
||||
uint8_t flash_stream_submit(uint16_t mode, uint8_t size)
|
||||
{
|
||||
uint8_t b = fs.block;
|
||||
uint16_t p = fs.page;
|
||||
uint8_t r = fs.status & ~FS_Ready;
|
||||
mode |= (uint16_t)config.flash_page_size << 8;
|
||||
if (size) {
|
||||
if (b & 8) {
|
||||
b = 0;
|
||||
fs.page = ++p;
|
||||
fs.npages--;
|
||||
}
|
||||
if (b==7 && r & FS_BCH) {
|
||||
size |= 16;
|
||||
memcpy(flash_buffer+64, bch_parity, 16);
|
||||
}
|
||||
}
|
||||
else if ((r & FS_Dir) == FS_Erase) {
|
||||
fs.page += (uint16_t) b + 1;
|
||||
fs.npages -= (uint16_t) b + 1;
|
||||
b = 8;
|
||||
}
|
||||
fs.block = b+1;
|
||||
|
||||
uint8_t e = flash_cmd(mode, size, p, (uint16_t)(b&7) << 6);
|
||||
if (e)
|
||||
r |= FS_Ready; // FS_Error
|
||||
r |= FS_Busy;
|
||||
fs.status = r;
|
||||
return e;
|
||||
}
|
||||
|
||||
__attribute__ ((noinline, noclone))
|
||||
uint8_t flash_stream_done()
|
||||
{
|
||||
uint8_t r = fs.status & FS_Error;
|
||||
if (!r || r == FS_Error)
|
||||
return 1;
|
||||
if (fs.npages || !(fs.block & 8))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline
|
||||
uint8_t flash_write_next_block()
|
||||
{
|
||||
return flash_stream_submit(config.write_buffer, 64);
|
||||
}
|
||||
|
||||
static inline
|
||||
uint8_t flash_read_next_block()
|
||||
{
|
||||
uint16_t mode;
|
||||
if (fs.page & 0x1000)
|
||||
mode = config.read_buffer[fs.page&1];
|
||||
else
|
||||
mode = config.read_array;
|
||||
return flash_stream_submit(mode, 64);
|
||||
}
|
||||
|
||||
static inline
|
||||
uint8_t flash_erase_next_page()
|
||||
{
|
||||
uint16_t mode = 0x81; // Page Erase
|
||||
uint8_t n = 0;
|
||||
if (fs.page && !(fs.page & 0xff) && fs.npages & 0xff00) {
|
||||
mode = 0x7c; // Sector 1…15 Erase
|
||||
n = 0xff;
|
||||
}
|
||||
else if (!(fs.page & 7) && fs.npages >= 8) {
|
||||
mode = 0x50; // Block Erase
|
||||
n = 7;
|
||||
}
|
||||
fs.block = n;
|
||||
return flash_stream_submit(mode, 0);
|
||||
}
|
||||
|
||||
static inline
|
||||
uint8_t flash_burn_page()
|
||||
{
|
||||
return flash_stream_submit(config.burn_page, 0);
|
||||
}
|
||||
|
||||
static inline
|
||||
void bch_flash_buffer(uint8_t n)
|
||||
{
|
||||
bch4369_str(flash_buffer, n);
|
||||
}
|
||||
|
||||
void bch_flash_init()
|
||||
{
|
||||
bch4369_init();
|
||||
}
|
||||
|
||||
uint8_t flash_poll(uint8_t rr)
|
||||
{
|
||||
uint8_t r = fs.status;
|
||||
if (spi_busy_p()) {
|
||||
if (rr)
|
||||
goto collision;
|
||||
fs.status = r | FS_Busy;
|
||||
return r;
|
||||
}
|
||||
if ((r & FS_Error) == FS_Error)
|
||||
return r;
|
||||
if (r & FS_StBsy) {
|
||||
// status bytes arrived
|
||||
if (flash_status_bytes[0] & 0x80)
|
||||
// flash is still busy burning
|
||||
goto rd_status;
|
||||
// not busy any more, move Bsy → Rdy
|
||||
if (r & FS_Busy)
|
||||
r |= FS_Ready;
|
||||
goto ready;
|
||||
}
|
||||
if (!(r & FS_Busy))
|
||||
goto ready;
|
||||
if (rr) {
|
||||
collision:
|
||||
r |= FS_Error;
|
||||
fs.status = r;
|
||||
return r;
|
||||
}
|
||||
if (r & FS_Write) {
|
||||
if (fs.block == 9) {
|
||||
rd_status:
|
||||
// request status bytes for pending Write or Error
|
||||
r |= FS_StBsy;
|
||||
fs.status = r;
|
||||
flash_cmd_na(0xd7, 0xff02);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
else if (r & FS_BCH) {
|
||||
// checksum the received buffer
|
||||
if (fs.block == 1)
|
||||
bch_flash_init();
|
||||
if (fs.block & 8)
|
||||
bch_flash_buffer(80);
|
||||
else
|
||||
bch_flash_buffer(64);
|
||||
}
|
||||
|
||||
ready:
|
||||
if (rr)
|
||||
r |= FS_Ack;
|
||||
// clear the Bsy bits
|
||||
r &= ~(FS_Busy | FS_StBsy);
|
||||
fs.status = r;
|
||||
if (r & FS_Dir == FS_Write && fs.block == 8)
|
||||
flash_burn_page();
|
||||
else if (!flash_stream_done()) {
|
||||
if (r & (FS_Dir|FS_Ack) == (FS_Read|FS_Ack))
|
||||
flash_read_next_block();
|
||||
else if (r & (FS_Dir|FS_Ack) == (FS_Write|FS_Ack)) {
|
||||
if (r & FS_BCH) {
|
||||
if (!(fs.block & 7))
|
||||
bch_flash_init();
|
||||
bch_flash_buffer(64);
|
||||
}
|
||||
flash_write_next_block();
|
||||
}
|
||||
else if (r & FS_Dir == FS_Erase)
|
||||
flash_erase_next_page();
|
||||
}
|
||||
return fs.status;
|
||||
}
|
||||
|
||||
uint8_t flash_start_stream(uint16_t page, uint16_t npages, uint8_t flags)
|
||||
{
|
||||
uint8_t r = flash_poll(0);
|
||||
if ((r & FS_Error) == FS_Busy)
|
||||
return FS_Error;
|
||||
r = flags | FS_Ready;
|
||||
if (config.flash_page_size != FM_528)
|
||||
r &=~ FS_BCH;
|
||||
fs.page = page;
|
||||
fs.block = 0;
|
||||
fs.npages = npages;
|
||||
fs.status = r;
|
||||
flash_status_bytes[0] = 0xff;
|
||||
return flash_poll(0);
|
||||
}
|
||||
|
|
|
|||
54
src/flash.h
54
src/flash.h
|
|
@ -2,23 +2,49 @@
|
|||
#include "spi.h"
|
||||
|
||||
enum flash_mode_bits {
|
||||
FM_PAD1 = 0x01,
|
||||
FM_PAD2 = 0x02,
|
||||
FM_PAD4 = 0x03,
|
||||
FM_PAD = 0x03,
|
||||
FM_512 = 0x04,
|
||||
FM_528 = 0x08,
|
||||
FM_SEC = 0x0c,
|
||||
FM_ADDR = 0x0c,
|
||||
FM_WRITE = 0x10,
|
||||
FM_READ = 0x20,
|
||||
FM_WAIT = 0x30,
|
||||
FM_START = 0x30,
|
||||
FM_CONT = SPI_CONT,
|
||||
FM_PAD1 = 0x0100,
|
||||
FM_PAD2 = 0x0200,
|
||||
FM_PAD4 = 0x0300,
|
||||
FM_PAD = 0x0300,
|
||||
FM_512 = 0x0400,
|
||||
FM_528 = 0x0800,
|
||||
FM_SEC = 0x0c00,
|
||||
FM_ADDR = 0x0c00,
|
||||
FM_WRITE = 0x1000,
|
||||
FM_READ = 0x2000,
|
||||
FM_WAIT = 0x3000,
|
||||
FM_START = 0x3000,
|
||||
FM_CONT = (uint16_t)SPI_CONT << 8,
|
||||
FM_SPI = FM_CONT,
|
||||
FM_NSTR = 0x8000,
|
||||
};
|
||||
|
||||
uint8_t flash_cmd_na(uint16_t mode, uint16_t what);
|
||||
uint8_t flash_cmd(uint16_t mode, uint16_t what, uint16_t page, uint16_t byte);
|
||||
#define FB_SIZE 64
|
||||
#define FB_SIZE 80
|
||||
extern uint8_t flash_buffer[FB_SIZE];
|
||||
uint8_t flash_submit_command(uint8_t *cmd);
|
||||
uint8_t flash_start_stream(uint16_t page, uint16_t npages, uint8_t flags);
|
||||
uint8_t flash_poll(uint8_t rr);
|
||||
|
||||
extern
|
||||
struct flash_stream {
|
||||
uint16_t page; // page address of buffer number
|
||||
uint16_t npages; // more pages to read
|
||||
uint8_t block; // next block to read 0…9
|
||||
uint8_t status; // FS_… flags
|
||||
} fs;
|
||||
|
||||
enum {
|
||||
FS_Ready = 1, // ready for the next buffer
|
||||
FS_Busy = 2, // processing …
|
||||
FS_Error = 3, // Aborted
|
||||
FS_Read = 4, // array read
|
||||
FS_Write = 8, // buffer write and burn
|
||||
FS_Erase = 12, // Erase
|
||||
FS_Dir = 12, // Mask for the last three
|
||||
FS_Ack = 32, // Next buffer is provided, continue …
|
||||
FS_StBsy = 64, // Waiting to Flash status register
|
||||
FS_BCH = 128, // do 528 byte pages.
|
||||
};
|
||||
|
||||
|
|
|
|||
22
src/pipe.c
Normal file
22
src/pipe.c
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
#include <pipe.h>
|
||||
|
||||
struct pipe pipe;
|
||||
|
||||
struct pipe_config {
|
||||
uint8_t source;
|
||||
uint8_t dest;
|
||||
uint16_t npages;
|
||||
uint8_t flash_flags;
|
||||
uint8_t flash_page;
|
||||
};
|
||||
|
||||
uint8_t pipe_config(const uint8_t *, uint8_t flag)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
uint8_t pipe_poll(uint8_t flag)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
20
src/pipe.h
Normal file
20
src/pipe.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t pipe_config(const uint8_t *, uint8_t flag);
|
||||
uint8_t pipe_poll(uint8_t flag);
|
||||
|
||||
enum pipe_ports {
|
||||
pipe_cmd = 1,
|
||||
pipe_hk = 2,
|
||||
pipe_flash = 4,
|
||||
pipe_fpgs = 8,
|
||||
};
|
||||
|
||||
extern
|
||||
struct pipe {
|
||||
uint8_t source;
|
||||
uint8_t dest;
|
||||
uint8_t status;
|
||||
uint16_t size;
|
||||
} pipe;
|
||||
Loading…
Add table
Add a link
Reference in a new issue