Checkpoint EEPROM, firmware analysis and instrument protocol updates
This commit is contained in:
44
c/set-protocol/include/balsam167_eeprom_block.h
Normal file
44
c/set-protocol/include/balsam167_eeprom_block.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* Private PM35 FC03 EEPROM window; not standard Modbus register quantities.
|
||||
* AT25256B keeps its existing 0x8000..0xBFFF / count 1..120 requests.
|
||||
* M95M02 uses four 64-KiB windows: count bit15 marks the profile, bits9:8
|
||||
* select bank 0..3, bits7:0 carry word count. Address 0x8000..0xFFFF is
|
||||
* the word offset within a bank. Every request is self-contained; no global
|
||||
* bank register can be changed by another client. Old firmware rejects the
|
||||
* marked quantity. Neither profile silently reads the other memory type.
|
||||
*/
|
||||
#ifndef BALSAM167_EEPROM_BLOCK_H
|
||||
#define BALSAM167_EEPROM_BLOCK_H
|
||||
#include "balsam167_eeprom_layout.h"
|
||||
#define BALSAM167_EEPROM_RTU_BASE 0x8000U
|
||||
#define BALSAM167_EEPROM_BLOCK_WORDS 120U
|
||||
#define BALSAM167_EEPROM_M95_MARKER 0x8000U
|
||||
#define BALSAM167_EEPROM_WRITE_M95 0x44U
|
||||
static unsigned long balsam167_eeprom_capacity(unsigned profile)
|
||||
{
|
||||
return profile == 0 ? 32768UL : (profile == 1 ? 262144UL : 0UL);
|
||||
}
|
||||
static unsigned long balsam167_eeprom_block_word(unsigned address, unsigned count)
|
||||
{
|
||||
return ((unsigned long)(count & 0x0300U) << 7) + (address - 0x8000U);
|
||||
}
|
||||
static unsigned balsam167_eeprom_block_valid_profile(unsigned fn, unsigned address,
|
||||
unsigned count, unsigned profile)
|
||||
{
|
||||
unsigned n = count & 255U;
|
||||
unsigned long word;
|
||||
if (fn != 3 || address < 0x8000U || !n || n > 120U) return 0;
|
||||
if (profile == 0) return count == n && address < 0xC000U && n <= 0xC000U-address;
|
||||
if (profile != 1 || (count & 0xFC00U) != 0x8000U) return 0;
|
||||
word = balsam167_eeprom_block_word(address, count);
|
||||
return n <= 0x10000UL-address && word+n <= 131072UL;
|
||||
}
|
||||
static unsigned balsam167_eeprom_block_valid(unsigned fn, unsigned address, unsigned count)
|
||||
{
|
||||
#if EEPROM_M95M02
|
||||
return balsam167_eeprom_block_valid_profile(fn, address, count, 1);
|
||||
#else
|
||||
return fn == 3 && address >= 0x8000U && address < 0xC000U &&
|
||||
count && count <= 120U && count <= 0xC000U-address;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -5,8 +5,20 @@
|
||||
*/
|
||||
#ifndef BALSAM167_EEPROM_LAYOUT_H
|
||||
#define BALSAM167_EEPROM_LAYOUT_H
|
||||
#define BALSAM167_EEPROM_BYTES 0x8000
|
||||
/* EEPROM_M95M02 is selected by the board configuration, never autodetected
|
||||
* by writing test patterns. Keep numeric constants usable by the TI linker. */
|
||||
#define BALSAM167_AT25256_BYTES 0x8000
|
||||
#define BALSAM167_M95M02_BYTES 0x40000
|
||||
#ifndef EEPROM_M95M02
|
||||
#define EEPROM_M95M02 0
|
||||
#endif
|
||||
#if EEPROM_M95M02
|
||||
#define BALSAM167_EEPROM_BYTES BALSAM167_M95M02_BYTES
|
||||
#define BALSAM167_EEPROM_PAGE_BYTES 256
|
||||
#else
|
||||
#define BALSAM167_EEPROM_BYTES BALSAM167_AT25256_BYTES
|
||||
#define BALSAM167_EEPROM_PAGE_BYTES 64
|
||||
#endif
|
||||
#define BALSAM167_EEPROM_PARAM_WORDS 129
|
||||
#define BALSAM167_EEPROM_WORDS (BALSAM167_EEPROM_BYTES / 2)
|
||||
/* Preserve the historical end-exclusive parameter boundary. The final word
|
||||
|
||||
@@ -91,6 +91,16 @@ PCAN_ABI_API size_t pcan_abi_periph28335_eeprom_request(const void *state,
|
||||
PCAN_ABI_API int pcan_abi_periph28335_eeprom_accept(void *state,
|
||||
const uint8_t *reply, size_t size, uint8_t *output, size_t capacity);
|
||||
PCAN_ABI_API uint32_t pcan_abi_periph28335_eeprom_capacity(void);
|
||||
PCAN_ABI_API uint32_t pcan_abi_periph28335_eeprom_capacity_profile(unsigned profile);
|
||||
PCAN_ABI_API int pcan_abi_periph28335_eeprom_begin_profile(void *r, uint32_t c, uint32_t a, uint32_t n, unsigned profile);
|
||||
PCAN_ABI_API size_t pcan_abi_periph28335_eeprom_block_expected_profile(const void *r, unsigned profile);
|
||||
PCAN_ABI_API size_t pcan_abi_periph28335_eeprom_block_request_profile(const void *r, uint8_t *o, size_t n, unsigned profile);
|
||||
PCAN_ABI_API int pcan_abi_periph28335_eeprom_block_accept_profile(void *r, const uint8_t *p, size_t n, uint8_t *o, size_t cap, unsigned profile);
|
||||
PCAN_ABI_API size_t pcan_abi_periph28335_eeprom_write_profile(uint32_t controller, uint32_t destination, uint32_t source, uint32_t length, unsigned profile, uint8_t *out, size_t cap);
|
||||
PCAN_ABI_API size_t pcan_abi_periph28335_eeprom_block_expected(const void *state);
|
||||
PCAN_ABI_API size_t pcan_abi_periph28335_eeprom_block_request(const void *state, uint8_t *out, size_t cap);
|
||||
PCAN_ABI_API int pcan_abi_periph28335_eeprom_block_accept(void *state, const uint8_t *reply, size_t size, uint8_t *out, size_t cap);
|
||||
|
||||
PCAN_ABI_API size_t pcan_abi_periph28335_append_crc(
|
||||
const uint8_t *payload, size_t payload_size,
|
||||
uint8_t *output, size_t output_size);
|
||||
|
||||
@@ -50,6 +50,22 @@ size_t periph28335_eeprom_request(const periph28335_eeprom_reader *reader,
|
||||
int periph28335_eeprom_accept(periph28335_eeprom_reader *reader,
|
||||
const uint8_t *reply, size_t size, uint8_t *output, size_t capacity);
|
||||
|
||||
/* FC03 block reader uses the same state/physical byte range as legacy PEEK.
|
||||
* expected() is the exact response length. No state advance on CRC/size error. */
|
||||
size_t periph28335_eeprom_block_expected(const periph28335_eeprom_reader *r);
|
||||
size_t periph28335_eeprom_block_request(const periph28335_eeprom_reader *r, uint8_t *out, size_t cap);
|
||||
int periph28335_eeprom_block_accept(periph28335_eeprom_reader *r,
|
||||
const uint8_t *reply, size_t size, uint8_t *out, size_t cap);
|
||||
|
||||
/* Profile 0 = AT25256B, 1 = M95M02; stable additional API for every host port.
|
||||
* State remains four uint32_t fields. M95 requires block mode, no PEEK fallback. */
|
||||
uint32_t periph28335_eeprom_capacity_profile(unsigned profile);
|
||||
int periph28335_eeprom_begin_profile(periph28335_eeprom_reader *r, uint32_t c, uint32_t a, uint32_t n, unsigned profile);
|
||||
size_t periph28335_eeprom_block_expected_profile(const periph28335_eeprom_reader *r, unsigned profile);
|
||||
size_t periph28335_eeprom_block_request_profile(const periph28335_eeprom_reader *r, uint8_t *o, size_t n, unsigned profile);
|
||||
int periph28335_eeprom_block_accept_profile(periph28335_eeprom_reader *r, const uint8_t *p, size_t n, uint8_t *o, size_t cap, unsigned profile);
|
||||
size_t periph28335_eeprom_write_profile(uint32_t controller, uint32_t destination, uint32_t source, uint32_t length, unsigned profile, uint8_t *out, size_t cap);
|
||||
|
||||
typedef enum {
|
||||
PERIPH28335_OK = 0,
|
||||
PERIPH28335_ERROR_ARGUMENT = -1,
|
||||
|
||||
@@ -380,6 +380,26 @@ int pcan_abi_gui_parser_stats(const void *parser_storage, uint32_t *frames,
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t pcan_abi_periph28335_eeprom_block_expected(const void *s)
|
||||
{ return periph28335_eeprom_block_expected((const periph28335_eeprom_reader *)s); }
|
||||
size_t pcan_abi_periph28335_eeprom_block_request(const void *s, uint8_t *out, size_t cap)
|
||||
{ return periph28335_eeprom_block_request((const periph28335_eeprom_reader *)s,out,cap); }
|
||||
int pcan_abi_periph28335_eeprom_block_accept(void *s, const uint8_t *reply, size_t size, uint8_t *out, size_t cap)
|
||||
{ return periph28335_eeprom_block_accept((periph28335_eeprom_reader *)s,reply,size,out,cap); }
|
||||
|
||||
uint32_t pcan_abi_periph28335_eeprom_capacity_profile(unsigned p)
|
||||
{ return periph28335_eeprom_capacity_profile(p); }
|
||||
int pcan_abi_periph28335_eeprom_begin_profile(void *s, uint32_t c, uint32_t a, uint32_t n, unsigned p)
|
||||
{ return periph28335_eeprom_begin_profile((periph28335_eeprom_reader *)s,c,a,n,p); }
|
||||
size_t pcan_abi_periph28335_eeprom_block_expected_profile(const void *s, unsigned p)
|
||||
{ return periph28335_eeprom_block_expected_profile((const periph28335_eeprom_reader *)s,p); }
|
||||
size_t pcan_abi_periph28335_eeprom_block_request_profile(const void *s, uint8_t *o, size_t n, unsigned p)
|
||||
{ return periph28335_eeprom_block_request_profile((const periph28335_eeprom_reader *)s,o,n,p); }
|
||||
int pcan_abi_periph28335_eeprom_block_accept_profile(void *s, const uint8_t *r, size_t n, uint8_t *o, size_t cap, unsigned p)
|
||||
{ return periph28335_eeprom_block_accept_profile((periph28335_eeprom_reader *)s,r,n,o,cap,p); }
|
||||
size_t pcan_abi_periph28335_eeprom_write_profile(uint32_t c, uint32_t d, uint32_t s, uint32_t n, unsigned p, uint8_t *o, size_t cap)
|
||||
{ return periph28335_eeprom_write_profile(c,d,s,n,p,o,cap); }
|
||||
|
||||
int pcan_abi_tms2812_bus_step(int write, unsigned step, unsigned tetrad, unsigned reg,
|
||||
uint16_t data, uint32_t *address, uint16_t *value, uint8_t *command)
|
||||
{
|
||||
|
||||
@@ -9,22 +9,24 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "set_crc.h"
|
||||
#include "balsam167_eeprom_block.h"
|
||||
|
||||
static int eeprom_reader_valid(const periph28335_eeprom_reader *r, unsigned profile)
|
||||
|
||||
static int eeprom_reader_valid(const periph28335_eeprom_reader *r)
|
||||
{
|
||||
return r && r->controller >= 1U && r->controller <= 255U &&
|
||||
r->start < PERIPH28335_EEPROM_BYTES && r->length &&
|
||||
r->length <= PERIPH28335_EEPROM_BYTES - r->start && r->received < r->length;
|
||||
r->start < balsam167_eeprom_capacity(profile) && r->length &&
|
||||
r->length <= balsam167_eeprom_capacity(profile) - r->start && r->received < r->length;
|
||||
}
|
||||
|
||||
int periph28335_eeprom_begin(periph28335_eeprom_reader *r,
|
||||
uint32_t controller, uint32_t start, uint32_t length)
|
||||
int periph28335_eeprom_begin_profile(periph28335_eeprom_reader *r,
|
||||
uint32_t controller, uint32_t start, uint32_t length, unsigned profile)
|
||||
{
|
||||
if (!r) return PERIPH28335_ERROR_ARGUMENT;
|
||||
/* Invalidate first: a rejected new range must not leave an old read active. */
|
||||
memset(r, 0, sizeof(*r));
|
||||
if (!controller || controller > 255U || start >= PERIPH28335_EEPROM_BYTES ||
|
||||
!length || length > PERIPH28335_EEPROM_BYTES - start)
|
||||
if (!controller || controller > 255U || start >= balsam167_eeprom_capacity(profile) ||
|
||||
!length || length > balsam167_eeprom_capacity(profile) - start)
|
||||
return PERIPH28335_ERROR_RANGE;
|
||||
r->controller = controller; r->start = start; r->length = length;
|
||||
return PERIPH28335_OK;
|
||||
@@ -35,7 +37,7 @@ size_t periph28335_eeprom_request(const periph28335_eeprom_reader *r,
|
||||
{
|
||||
uint8_t payload[6];
|
||||
uint32_t word;
|
||||
if (!eeprom_reader_valid(r)) return 0;
|
||||
if (!eeprom_reader_valid(r, 0)) return 0;
|
||||
word = (r->start + r->received) / 2U;
|
||||
payload[0] = (uint8_t)r->controller; payload[1] = 56U; /* CMD_PEEK only */
|
||||
/* 167 routes words 0..0x3fff to SPI EEPROM. The old terminal's
|
||||
@@ -49,7 +51,7 @@ int periph28335_eeprom_accept(periph28335_eeprom_reader *r,
|
||||
const uint8_t *reply, size_t size, uint8_t *output, size_t capacity)
|
||||
{
|
||||
unsigned odd, count;
|
||||
if (!eeprom_reader_valid(r) || !reply || !output) return PERIPH28335_ERROR_ARGUMENT;
|
||||
if (!eeprom_reader_valid(r, 0) || !reply || !output) return PERIPH28335_ERROR_ARGUMENT;
|
||||
/* The UART layer may strip two legacy zero-padding bytes after CRC. */
|
||||
if (size != 8U && size != 10U) return PERIPH28335_ERROR_LENGTH;
|
||||
if (periph28335_crc16_modbus(reply, 8U) != 0) return PERIPH28335_ERROR_CRC;
|
||||
@@ -64,6 +66,87 @@ int periph28335_eeprom_accept(periph28335_eeprom_reader *r,
|
||||
return (int)count;
|
||||
}
|
||||
|
||||
/* One common codec for all host ports. Physical EEPROM bytes already have
|
||||
* network-word order; only trim an odd first/last byte, never swap them. */
|
||||
static unsigned eeprom_block_words(const periph28335_eeprom_reader *r, unsigned profile)
|
||||
{
|
||||
uint32_t n;
|
||||
if (!eeprom_reader_valid(r, profile)) return 0;
|
||||
n = (r->length - r->received + ((r->start + r->received) & 1U) + 1U) / 2U;
|
||||
/* A response cannot cross a bank boundary; trim the last block there. */
|
||||
if (n > 32768U - ((r->start+r->received)/2U % 32768U))
|
||||
n = 32768U - ((r->start+r->received)/2U % 32768U);
|
||||
return (unsigned)(n > BALSAM167_EEPROM_BLOCK_WORDS ? BALSAM167_EEPROM_BLOCK_WORDS : n);
|
||||
}
|
||||
size_t periph28335_eeprom_block_expected_profile(const periph28335_eeprom_reader *r, unsigned profile)
|
||||
{
|
||||
unsigned n = eeprom_block_words(r, profile);
|
||||
return n ? 5U + 2U*n : 0;
|
||||
}
|
||||
size_t periph28335_eeprom_block_request_profile(const periph28335_eeprom_reader *r, uint8_t *out, size_t cap, unsigned profile)
|
||||
{
|
||||
uint8_t p[6];
|
||||
unsigned n = eeprom_block_words(r, profile), a, quantity;
|
||||
uint32_t word;
|
||||
if (!n) return 0;
|
||||
word = (r->start + r->received) / 2U;
|
||||
a = 0x8000U + (unsigned)(word % 32768U);
|
||||
quantity = n | (profile ? (0x8000U | (unsigned)(word/32768U)*256U) : 0U);
|
||||
if (!balsam167_eeprom_block_valid_profile(3,a,quantity,profile)) return 0;
|
||||
p[0]=(uint8_t)r->controller; p[1]=3;
|
||||
p[2]=(uint8_t)(a>>8); p[3]=(uint8_t)a; p[4]=(uint8_t)(quantity>>8); p[5]=(uint8_t)quantity;
|
||||
return periph28335_append_crc(p,6,out,cap);
|
||||
}
|
||||
int periph28335_eeprom_block_accept_profile(periph28335_eeprom_reader *r,
|
||||
const uint8_t *reply, size_t size, uint8_t *out, size_t cap, unsigned profile)
|
||||
{
|
||||
unsigned n=eeprom_block_words(r, profile), odd, count;
|
||||
if (!n || !reply || !out) return PERIPH28335_ERROR_ARGUMENT;
|
||||
if (size != 5U+2U*n) return PERIPH28335_ERROR_LENGTH;
|
||||
if (periph28335_crc16_modbus(reply,size)) return PERIPH28335_ERROR_CRC;
|
||||
/* Common address 16 is answered by the board's own Mode, 5 or 6. */
|
||||
if ((reply[0] != r->controller && !(r->controller==16 && (reply[0]==5 || reply[0]==6))) ||
|
||||
reply[1]!=3 || reply[2]!=2U*n) return PERIPH28335_ERROR_HEADER;
|
||||
odd=(unsigned)((r->start+r->received)&1U);
|
||||
count=2U*n-odd;
|
||||
if (count>r->length-r->received) count=(unsigned)(r->length-r->received);
|
||||
if (cap<count) return PERIPH28335_ERROR_CAPACITY;
|
||||
memcpy(out,reply+3+odd,count);
|
||||
r->received+=count;
|
||||
return (int)count;
|
||||
}
|
||||
|
||||
/* Keep all existing exported symbols and the 16-byte reader ABI unchanged. */
|
||||
int periph28335_eeprom_begin(periph28335_eeprom_reader *r, uint32_t c, uint32_t a, uint32_t n)
|
||||
{ return periph28335_eeprom_begin_profile(r,c,a,n,0); }
|
||||
size_t periph28335_eeprom_block_expected(const periph28335_eeprom_reader *r)
|
||||
{ return periph28335_eeprom_block_expected_profile(r,0); }
|
||||
size_t periph28335_eeprom_block_request(const periph28335_eeprom_reader *r, uint8_t *o, size_t n)
|
||||
{ return periph28335_eeprom_block_request_profile(r,o,n,0); }
|
||||
int periph28335_eeprom_block_accept(periph28335_eeprom_reader *r, const uint8_t *p, size_t n, uint8_t *o, size_t cap)
|
||||
{ return periph28335_eeprom_block_accept_profile(r,p,n,o,cap,0); }
|
||||
uint32_t periph28335_eeprom_capacity_profile(unsigned profile)
|
||||
{ return (uint32_t)balsam167_eeprom_capacity(profile); }
|
||||
/* Legacy EXTEND carries word addresses and octet lengths. A distinct M95
|
||||
* subcommand makes a wrong-profile write fail closed on either firmware. */
|
||||
size_t periph28335_eeprom_write_profile(uint32_t controller, uint32_t destination,
|
||||
uint32_t source, uint32_t length, unsigned profile, uint8_t *out, size_t cap)
|
||||
{
|
||||
uint8_t p[16]; unsigned i;
|
||||
uint32_t capacity = periph28335_eeprom_capacity_profile(profile);
|
||||
uint32_t limit = capacity ? capacity-(BALSAM167_EEPROM_PARAM_WORDS+1U)*2U : 0;
|
||||
if (!controller || controller>255U || !length || length>199993U ||
|
||||
destination>=limit/2U || length>limit-destination*2U) return 0;
|
||||
p[0]=(uint8_t)controller; p[1]=60;
|
||||
for(i=0;i<4;i++) {
|
||||
p[2+i]=(uint8_t)(destination>>(8*i));
|
||||
p[6+i]=(uint8_t)(source>>(8*i));
|
||||
p[10+i]=(uint8_t)(length>>(8*i));
|
||||
}
|
||||
p[14]=(uint8_t)(profile ? BALSAM167_EEPROM_WRITE_M95 : 4); p[15]=0;
|
||||
return periph28335_append_crc(p,16,out,cap);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *project;
|
||||
const char *commands[PERIPH28335_COMMAND_COUNT];
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "periph28335.h"
|
||||
#include <assert.h>
|
||||
#include "balsam167_eeprom_block.h"
|
||||
#include <string.h>
|
||||
|
||||
static void response(uint8_t *out, unsigned high, unsigned low)
|
||||
@@ -12,9 +13,100 @@ static void response(uint8_t *out, unsigned high, unsigned low)
|
||||
out[8]=out[9]=0;
|
||||
}
|
||||
|
||||
static void blocks(void)
|
||||
{
|
||||
periph28335_eeprom_reader r;
|
||||
uint8_t req[8], reply[245], out[240];
|
||||
unsigned start, transactions, n, a, i, old;
|
||||
int got;
|
||||
assert(!balsam167_eeprom_block_valid(6,0x8000,1));
|
||||
assert(!balsam167_eeprom_block_valid(3,0xbfff,2));
|
||||
assert(!balsam167_eeprom_block_valid(3,0xffff,120));
|
||||
assert(!balsam167_eeprom_block_valid(3,0x8000,121));
|
||||
assert(!balsam167_eeprom_block_valid(3,0x8000,0));
|
||||
assert(balsam167_eeprom_block_valid(3,0xbfff,1));
|
||||
for(start=0;start<2;start++) {
|
||||
assert(!periph28335_eeprom_begin(&r,16,start,32768-start));
|
||||
transactions=0;
|
||||
while(r.received<r.length) {
|
||||
assert(periph28335_eeprom_block_request(&r,req,8)==8);
|
||||
assert(!periph28335_crc16_modbus(req,8));
|
||||
a=((unsigned)req[2]*256+req[3]-0x8000)*2;
|
||||
n=req[5]; assert(n && n<=120 && a+2*n<=32768);
|
||||
reply[0]=5; reply[1]=3; reply[2]=(uint8_t)(2*n);
|
||||
for(i=0;i<2*n;i++) reply[3+i]=(uint8_t)(a+i);
|
||||
assert(periph28335_append_crc(reply,3+2*n,reply,sizeof reply)==5+2*n);
|
||||
old=r.received;
|
||||
reply[4]^=1;
|
||||
assert(periph28335_eeprom_block_accept(&r,reply,5+2*n,out,240)==PERIPH28335_ERROR_CRC);
|
||||
assert(r.received==old); reply[4]^=1;
|
||||
assert(periph28335_eeprom_block_accept(&r,reply,5+2*n,out,0)==PERIPH28335_ERROR_CAPACITY);
|
||||
assert(r.received==old);
|
||||
got=periph28335_eeprom_block_accept(&r,reply,5+2*n,out,240);
|
||||
assert(got>0);
|
||||
for(i=0;i<(unsigned)got;i++) assert(out[i]==(uint8_t)(start+old+i));
|
||||
transactions++;
|
||||
}
|
||||
assert(transactions==137);
|
||||
assert(!periph28335_eeprom_block_request(&r,req,8));
|
||||
}
|
||||
}
|
||||
|
||||
static void profiles(void)
|
||||
{
|
||||
periph28335_eeprom_reader r;
|
||||
uint8_t req[18], reply[245], out[240];
|
||||
unsigned n, i, q, a, bankmask=0;
|
||||
uint32_t pos, before;
|
||||
assert(periph28335_eeprom_capacity_profile(0)==32768);
|
||||
assert(periph28335_eeprom_capacity_profile(1)==262144);
|
||||
assert(periph28335_eeprom_capacity_profile(2)==0);
|
||||
assert(periph28335_eeprom_begin_profile(&r,16,262143,2,1)<0);
|
||||
assert(periph28335_eeprom_begin_profile(&r,16,0,2,2)<0);
|
||||
assert(!balsam167_eeprom_block_valid_profile(3,0xffff,0x8078,1));
|
||||
assert(!balsam167_eeprom_block_valid_profile(3,0x8000,0x8401,1));
|
||||
assert(!balsam167_eeprom_block_valid_profile(3,0x8000,0x8001,0));
|
||||
assert(!balsam167_eeprom_block_valid_profile(3,0x8000,1,1));
|
||||
assert(balsam167_eeprom_block_valid_profile(3,0xffff,0x8301,1));
|
||||
/* Full 256-KiB dump from an odd start exercises every bank transition,
|
||||
* first/last byte trimming, CRC failure and exact physical byte order. */
|
||||
assert(!periph28335_eeprom_begin_profile(&r,16,1,262143,1));
|
||||
while(r.received<r.length) {
|
||||
assert(periph28335_eeprom_block_request_profile(&r,req,8,1)==8);
|
||||
assert(!periph28335_crc16_modbus(req,8));
|
||||
a=req[2]*256U+req[3]; q=req[4]*256U+req[5]; n=q&255U;
|
||||
assert(balsam167_eeprom_block_valid_profile(3,a,q,1));
|
||||
pos=balsam167_eeprom_block_word(a,q)*2UL;
|
||||
assert(pos == (r.start+r.received)/2*2);
|
||||
bankmask |= 1U << ((q>>8)&3U);
|
||||
assert(periph28335_eeprom_block_expected_profile(&r,1)==5+2*n);
|
||||
reply[0]=5; reply[1]=3; reply[2]=(uint8_t)(n*2);
|
||||
for(i=0;i<n*2;i++) reply[3+i]=(uint8_t)((pos+i)^((pos+i)>>16));
|
||||
periph28335_append_crc(reply,3+n*2,reply,sizeof(reply));
|
||||
before=r.received; reply[4]^=1;
|
||||
assert(periph28335_eeprom_block_accept_profile(&r,reply,5+2*n,out,240,1)==PERIPH28335_ERROR_CRC);
|
||||
assert(r.received==before); reply[4]^=1;
|
||||
assert(periph28335_eeprom_block_accept_profile(&r,reply,5+2*n,out,240,1)>0);
|
||||
for(i=0;i<r.received-before;i++) {
|
||||
pos=1+before+i;
|
||||
assert(out[i]==(uint8_t)(pos^(pos>>16)));
|
||||
}
|
||||
}
|
||||
assert(bankmask==15);
|
||||
assert(!periph28335_eeprom_block_request_profile(&r,req,8,1));
|
||||
assert(periph28335_eeprom_write_profile(5,0,0x200000,33514,0,req,18)==0);
|
||||
assert(periph28335_eeprom_write_profile(5,0,0x200000,33514,1,req,18)==18);
|
||||
assert(req[14]==0x44 && req[15]==0 && !periph28335_crc16_modbus(req,18));
|
||||
assert(!periph28335_eeprom_write_profile(5,0x1ff7e,0,2,1,req,18));
|
||||
assert(!periph28335_eeprom_write_profile(5,0xffffffff,0,2,1,req,18));
|
||||
assert(periph28335_eeprom_write_profile(5,0,0,32438,0,req,18)==18 && req[14]==4);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
periph28335_eeprom_reader reader;
|
||||
blocks();
|
||||
profiles();
|
||||
uint8_t request[8], reply[10], data[2];
|
||||
unsigned i;
|
||||
assert(sizeof(reader)==16);
|
||||
|
||||
Reference in New Issue
Block a user