Compare commits

...

2 commits

Author SHA1 Message Date
Stephan I. Böttcher
0514546b7d ssp job.count
- Replace `.idle_count` by `.count`
- Keep track of received and sent frames.
- Properly extend the job at a match.
2024-11-04 14:35:01 +01:00
Stephan I. Böttcher
c972a723c1 make %.s -fverbose-asm 2024-11-04 14:34:50 +01:00
6 changed files with 70 additions and 67 deletions

View file

@ -129,7 +129,7 @@ OBJS = crt.o $(patsubst %,%.o,$(sources))
objs: $(OBJS) objs: $(OBJS)
%.s: %.c %.s: %.c
$(CC) -S $(CFLAGS) $< $(CC) -fverbose-asm -S $(CFLAGS) $<
%.o: %.c %.o: %.c
$(CC) -MMD $(DEBUGFORMAT) -c $(CFLAGS) $< $(CC) -MMD $(DEBUGFORMAT) -c $(CFLAGS) $<

View file

@ -42,7 +42,7 @@ int ads8688(unsigned short *frame, int n, int flags, int timeout)
ssp_assert_ssel(); ssp_assert_ssel();
ssp_set_buffer(data.data, N); ssp_set_buffer(data.data, N);
ssp_set_read(1, n); ssp_set_read(1, n);
ssp_submit(frame, 1, n, 0); ssp_submit(frame, 1, n+1, 0);
int r = ssp_wait(timeout); int r = ssp_wait(timeout);
if (!r) if (!r)
ssp_deassert_ssel(); ssp_deassert_ssel();

View file

@ -12,7 +12,7 @@ int ltc2656(unsigned int frame, int flags, int timeout)
ssp_assert_ssel(); ssp_assert_ssel();
ssp_set_buffer(0,0); ssp_set_buffer(0,0);
unsigned short cmd[2] = { frame >> 16, frame & 0xffff }; unsigned short cmd[2] = { frame >> 16, frame & 0xffff };
ssp_submit(cmd, 2, 0, 0); ssp_submit(cmd, 2, 2, 0);
int r = ssp_wait(timeout); int r = ssp_wait(timeout);
if (!r) if (!r)
ssp_deassert_ssel(); ssp_deassert_ssel();

View file

@ -113,9 +113,10 @@ static const struct ssp_batch bate_batch[] = {
.flags = ssp_b_job, .flags = ssp_b_job,
{ .job = &(const struct ssp_job) { { .job = &(const struct ssp_job) {
.command = bate_cmds, .command = bate_cmds,
.count = 11,
.cmd_count = 11, .cmd_count = 11,
.read_count = 11, .read_count = 11,
.buf_count = 1, .buf_count = 11,
}}, }},
}, },
{ {
@ -126,6 +127,7 @@ static const struct ssp_batch bate_batch[] = {
.flags = ssp_b_job, .flags = ssp_b_job,
{ .job = &(const struct ssp_job) { { .job = &(const struct ssp_job) {
.command = bate_cmds+11, .command = bate_cmds+11,
.count = 2,
.cmd_count = 2, .cmd_count = 2,
.read_count = 2, .read_count = 2,
}}, }},
@ -137,7 +139,7 @@ static const struct ssp_batch bate_batch[] = {
{ {
.flags = ssp_b_job, .flags = ssp_b_job,
{ .job = &(const struct ssp_job) { { .job = &(const struct ssp_job) {
.idle_count = 1, .count = 1,
.read_count = 1, .read_count = 1,
}}, }},
}, },
@ -167,7 +169,7 @@ int read_pressure(int from_phase, int to_phase, int value)
ssp_assert_ssel(); ssp_assert_ssel();
ssp_set_buffer(pressure_reading, 8); ssp_set_buffer(pressure_reading, 8);
ssp_set_read(3, 8); ssp_set_read(3, 8);
r = ssp_submit(bate_cmds, 11, 0, 0); r = ssp_submit(bate_cmds, 11, 11, 0);
break; break;
case 2: case 2:
case 6: case 6:
@ -190,9 +192,9 @@ int read_pressure(int from_phase, int to_phase, int value)
break; break;
case 5: ssp_set_buffer(pressure_reading+6, 2); case 5: ssp_set_buffer(pressure_reading+6, 2);
ssp_set_read(0, 0); ssp_set_read(0, 0);
r = ssp_submit(bate_cmds+11, 2, 0, 1); r = ssp_submit(bate_cmds+11, 2, 2, 1);
break; break;
case 8: r = ssp_submit(bate_cmds+11, 1, 0, 1); case 8: r = ssp_submit(0, 0, 1, 1);
break; break;
case 10: case 10:
ssp_deassert_ssel(); ssp_deassert_ssel();

72
ssp.c
View file

@ -16,10 +16,10 @@ unsigned int ssp_bits;
int (*ssp_callback)(); int (*ssp_callback)();
volatile unsigned int ssp_lastword; volatile unsigned int ssp_lastword;
unsigned int ssp_ssel_mask = SSP_SSEL_MASK0 | SSP_SSEL_MASK1; unsigned int ssp_ssel_mask = SSP_SSEL_MASK0 | SSP_SSEL_MASK1;
static const struct timer_wait *ssp_batch_wait;
unsigned short *ssp_buffer; unsigned short *ssp_buffer;
volatile unsigned int ssp_frame_count; volatile int ssp_frames_sent;
volatile int ssp_frames_read;
unsigned short ssp_scratch[256]; unsigned short ssp_scratch[256];
@ -44,7 +44,7 @@ void ssp_set_buffer(short *buf, int size)
void ssp_poll(void) void ssp_poll(void)
{ {
volatile struct ssp_job *j=&job; volatile struct ssp_job *j=&job;
if (j->idle_count || j->read_count || j->cmd_count || SSPSR & (SSPSR_RNE|SSPSR_BSY)) if (j->count || SSPSR & (SSPSR_RNE|SSPSR_BSY))
SSPIMSC = SSP_INT_RX | SSP_INT_TX; SSPIMSC = SSP_INT_RX | SSP_INT_TX;
} }
@ -58,18 +58,22 @@ static void ssp_isr(void)
unsigned int sr = SSPSR; unsigned int sr = SSPSR;
unsigned int nread = 0; int nread = 0;
unsigned int rc = j->read_count; int rc = j->read_count;
while (sr&SSPSR_RNE) { while (sr&SSPSR_RNE) {
unsigned int dr = SSPDR; unsigned int dr = SSPDR;
sr=SSPSR; sr=SSPSR;
nread++; nread++;
ssp_lastword = ssp_lastword << ssp_bits | dr; ssp_lastword = ssp_lastword << ssp_bits | dr;
if (ssp_frame_count++ >= ssp_match.count if (ssp_frames_read++ >= ssp_match.frame_count
&& !rc && !rc
&& (dr & ssp_match.mask) == ssp_match.value) { && (dr & ssp_match.mask) == ssp_match.value) {
rc = ssp_match.size; rc = ssp_match.read_count;
j->idle_count = 0; if (ssp_match.count) {
j->count = ssp_match.count
+ ssp_match.frame_count
- ssp_frames_sent;
}
} }
if (rc) { if (rc) {
rc--; rc--;
@ -81,18 +85,19 @@ static void ssp_isr(void)
} }
} }
j->read_count = rc; j->read_count = rc;
int ic = j->count;
sr |= SSPSR; // race between SSPSR_BSY, SSPSR_RNE? sr |= SSPSR; // race between SSPSR_BSY, SSPSR_RNE?
if (!j->cmd_count && !j->idle_count) { if (!ic)
if (!rc && !(sr & (SSPSR_BSY|SSPSR_RNE))) { if ((sr & (SSPSR_BSY|SSPSR_RNE)))
goto outic;
else {
SSPIMSC = 0; SSPIMSC = 0;
if (ssp_callback) if (ssp_callback)
ssp_callback(); ssp_callback();
} goto out;
else
SSPIMSC = SSP_INT_RX;
goto out;
} }
else if (!(sr & (SSPSR_BSY|SSPSR_RNE))) else if (!(sr & (SSPSR_BSY|SSPSR_RNE)))
nread = 8; nread = 8;
@ -100,25 +105,24 @@ static void ssp_isr(void)
// This prevents Rx FIFO overflow. // This prevents Rx FIFO overflow.
// Except, when the Tx is not busy at all, then we can fill it up. // Except, when the Tx is not busy at all, then we can fill it up.
unsigned int ic = j->idle_count; while (ic && nread && (sr&SSPSR_TNF)) {
while (nread && (sr&SSPSR_TNF)) {
if (j->cmd_count) { if (j->cmd_count) {
j->cmd_count--; j->cmd_count--;
SSPDR = *j->command++; SSPDR = *j->command++;
} }
else if (ic) { else
ic--; SSPDR = j->idle_frame;
SSPDR = ssp_match.idle; ssp_frames_sent ++;
}
else {
SSPIMSC = SSP_INT_RX;
goto outic;
}
nread--; nread--;
ic--;
sr = SSPSR; sr = SSPSR;
} }
outic:
j->idle_count = ic; if (!ic)
outic:
SSPIMSC = SSP_INT_RX;
j->count = ic;
out: out:
VICVectAddr = 0; VICVectAddr = 0;
} }
@ -134,15 +138,16 @@ out:
// idle=0x8000 RFIFO, send what the acquisition fifos provide. // idle=0x8000 RFIFO, send what the acquisition fifos provide.
// idle=0x8001 NOOPP, just drain the FPGA buffer. // idle=0x8001 NOOPP, just drain the FPGA buffer.
int ssp_submit(const unsigned short *cmd, int cmd_size, unsigned int ic, unsigned int rc) int ssp_submit(const unsigned short *cmd, short cmd_size, unsigned short ic, unsigned short rc)
{ {
volatile struct ssp_job *j=&job; volatile struct ssp_job *j=&job;
unsigned int iflg = disable_irq(INT_DISABLE); unsigned int iflg = disable_irq(INT_DISABLE);
j->command = cmd; j->command = cmd;
j->cmd_count = cmd_size; j->cmd_count = cmd_size;
j->idle_count = ic; j->count = ic;
j->read_count = rc; j->read_count = rc;
ssp_frame_count = 0; ssp_frames_sent = 0;
ssp_frames_read = 0;
enable_irq(iflg); enable_irq(iflg);
ssp_poll(); ssp_poll();
return 0; return 0;
@ -158,6 +163,8 @@ int ssp_submit_job(const struct ssp_job *jj)
ssp_set_buffer(0, 0); ssp_set_buffer(0, 0);
} }
memcpy((void*)&job, jj, n); memcpy((void*)&job, jj, n);
ssp_frames_sent = 0;
ssp_frames_read = 0;
enable_irq(iflg); enable_irq(iflg);
ssp_poll(); ssp_poll();
return 0; return 0;
@ -168,8 +175,8 @@ void ssp_reset(void)
SSPIMSC = 0; SSPIMSC = 0;
volatile struct ssp_job *j=&job; volatile struct ssp_job *j=&job;
unsigned int iflg = disable_irq(INT_DISABLE); unsigned int iflg = disable_irq(INT_DISABLE);
j->count = 0;
j->cmd_count = 0; j->cmd_count = 0;
j->idle_count = 0;
j->read_count = 0; j->read_count = 0;
enable_irq(iflg); enable_irq(iflg);
} }
@ -218,7 +225,7 @@ int ssp_busy(void)
volatile struct ssp_job *j=&job; volatile struct ssp_job *j=&job;
ssp_poll(); // run the isr to drain the backlog ssp_poll(); // run the isr to drain the backlog
// j->* is volatile and we don't want races // j->* is volatile and we don't want races
unsigned int c = j->cmd_count + j->idle_count + j->read_count; unsigned int c = j->count;
if (c) if (c)
return c; return c;
// Hardware is busy // Hardware is busy
@ -386,7 +393,8 @@ const struct keywords ssp_variable_names[] = {
VARIABLE("ssp_response", (void *)&ssp_lastword), VARIABLE("ssp_response", (void *)&ssp_lastword),
VARIABLE("ssp_match", &ssp_match), VARIABLE("ssp_match", &ssp_match),
VARIABLE("ssp_ssel_mask", &ssp_ssel_mask), VARIABLE("ssp_ssel_mask", &ssp_ssel_mask),
VARIABLE("ssp_frame_count", (void *)&ssp_frame_count), VARIABLE("ssp_frames_sent", (void *)&ssp_frames_sent),
VARIABLE("ssp_frames_read", (void *)&ssp_frames_read),
VARIABLE("ssp_bits", &ssp_bits), VARIABLE("ssp_bits", &ssp_bits),
VARIABLE("ssp_config", &ssp_conf_default), VARIABLE("ssp_config", &ssp_conf_default),
VARIABLE("ssp_adc", &ssp_conf_adc), VARIABLE("ssp_adc", &ssp_conf_adc),

47
ssp.h
View file

@ -10,7 +10,7 @@ void ssp_reset(void);
void ssp_set_buffer(short *buf, int size); void ssp_set_buffer(short *buf, int size);
void ssp_poll(void); void ssp_poll(void);
int ssp_submit(const unsigned short *cmd, int cmd_size, unsigned int ic, unsigned int rc); int ssp_submit(const unsigned short *cmd, short cmd_size, unsigned short ic, unsigned short rc);
int ssp_busy(void); int ssp_busy(void);
int ssp_wait(int timeout); int ssp_wait(int timeout);
@ -23,7 +23,8 @@ extern unsigned int ssp_idle;
extern unsigned int ssp_match_mask; extern unsigned int ssp_match_mask;
extern unsigned int ssp_match_value; extern unsigned int ssp_match_value;
extern unsigned int ssp_match_count; extern unsigned int ssp_match_count;
extern volatile unsigned int ssp_frame_count; extern volatile int ssp_frames_sent;
extern volatile int ssp_frames_read;
extern unsigned short ssp_scratch[256]; extern unsigned short ssp_scratch[256];
extern int (*ssp_callback)(); extern int (*ssp_callback)();
@ -61,23 +62,26 @@ extern struct ssp_config ssp_confs[];
#define ssp_conf_dac ssp_confs[2] #define ssp_conf_dac ssp_confs[2]
#define ssp_conf_bate ssp_confs[3] #define ssp_conf_bate ssp_confs[3]
// volatile part of the job, inaccessible globally // volatile part of the job
// inaccessible globally
struct ssp_job { struct ssp_job {
unsigned int cmd_count; unsigned short cmd_count;
unsigned int read_count; unsigned short read_count;
unsigned int idle_count; unsigned short count;
unsigned short idle_frame;
const unsigned short *command; const unsigned short *command;
unsigned int buf_count; unsigned short buf_count;
unsigned short *buf_ptr; unsigned short *buf_ptr;
}; };
// global variables part of the job // global static variables for the job
// not changed by the isr
extern struct ssp_match { extern struct ssp_match {
unsigned int mask; unsigned char frame_count;
unsigned int value; unsigned char read_count;
unsigned int count; unsigned short count;
unsigned int idle; unsigned short mask;
unsigned int size; unsigned short value;
} ssp_match; } ssp_match;
struct ssp_batch; struct ssp_batch;
@ -116,23 +120,12 @@ enum ssp_batch_flags {
ssp_b_return = 0x80000000, ssp_b_return = 0x80000000,
}; };
// search for a pattern before recording frames
static inline
void ssp_set_match(unsigned int mask, unsigned int value,
unsigned int count, unsigned int size)
{
ssp_match.mask = mask;
ssp_match.value = value;
ssp_match.count = count;
ssp_match.size = size;
}
// skip `count` frames before recording `size` frames. // skip `count` frames before recording `size` frames.
static inline static inline
void ssp_set_read(unsigned int count, unsigned int size) void ssp_set_read(unsigned short count, unsigned short size)
{ {
ssp_match.count = count; ssp_match.frame_count = count;
ssp_match.size = size; ssp_match.read_count = size;
} }
int ssp_submit_job(const struct ssp_job *jj); int ssp_submit_job(const struct ssp_job *jj);