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)
%.s: %.c
$(CC) -S $(CFLAGS) $<
$(CC) -fverbose-asm -S $(CFLAGS) $<
%.o: %.c
$(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_set_buffer(data.data, N);
ssp_set_read(1, n);
ssp_submit(frame, 1, n, 0);
ssp_submit(frame, 1, n+1, 0);
int r = ssp_wait(timeout);
if (!r)
ssp_deassert_ssel();

View file

@ -12,7 +12,7 @@ int ltc2656(unsigned int frame, int flags, int timeout)
ssp_assert_ssel();
ssp_set_buffer(0,0);
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);
if (!r)
ssp_deassert_ssel();

View file

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

70
ssp.c
View file

@ -16,10 +16,10 @@ unsigned int ssp_bits;
int (*ssp_callback)();
volatile unsigned int ssp_lastword;
unsigned int ssp_ssel_mask = SSP_SSEL_MASK0 | SSP_SSEL_MASK1;
static const struct timer_wait *ssp_batch_wait;
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];
@ -44,7 +44,7 @@ void ssp_set_buffer(short *buf, int size)
void ssp_poll(void)
{
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;
}
@ -58,18 +58,22 @@ static void ssp_isr(void)
unsigned int sr = SSPSR;
unsigned int nread = 0;
unsigned int rc = j->read_count;
int nread = 0;
int rc = j->read_count;
while (sr&SSPSR_RNE) {
unsigned int dr = SSPDR;
sr=SSPSR;
nread++;
ssp_lastword = ssp_lastword << ssp_bits | dr;
if (ssp_frame_count++ >= ssp_match.count
if (ssp_frames_read++ >= ssp_match.frame_count
&& !rc
&& (dr & ssp_match.mask) == ssp_match.value) {
rc = ssp_match.size;
j->idle_count = 0;
rc = ssp_match.read_count;
if (ssp_match.count) {
j->count = ssp_match.count
+ ssp_match.frame_count
- ssp_frames_sent;
}
}
if (rc) {
rc--;
@ -81,18 +85,19 @@ static void ssp_isr(void)
}
}
j->read_count = rc;
int ic = j->count;
sr |= SSPSR; // race between SSPSR_BSY, SSPSR_RNE?
if (!j->cmd_count && !j->idle_count) {
if (!rc && !(sr & (SSPSR_BSY|SSPSR_RNE))) {
if (!ic)
if ((sr & (SSPSR_BSY|SSPSR_RNE)))
goto outic;
else {
SSPIMSC = 0;
if (ssp_callback)
ssp_callback();
}
else
SSPIMSC = SSP_INT_RX;
goto out;
}
else if (!(sr & (SSPSR_BSY|SSPSR_RNE)))
nread = 8;
@ -100,25 +105,24 @@ static void ssp_isr(void)
// This prevents Rx FIFO overflow.
// Except, when the Tx is not busy at all, then we can fill it up.
unsigned int ic = j->idle_count;
while (nread && (sr&SSPSR_TNF)) {
while (ic && nread && (sr&SSPSR_TNF)) {
if (j->cmd_count) {
j->cmd_count--;
SSPDR = *j->command++;
}
else if (ic) {
ic--;
SSPDR = ssp_match.idle;
}
else {
SSPIMSC = SSP_INT_RX;
goto outic;
}
else
SSPDR = j->idle_frame;
ssp_frames_sent ++;
nread--;
ic--;
sr = SSPSR;
}
outic:
j->idle_count = ic;
if (!ic)
outic:
SSPIMSC = SSP_INT_RX;
j->count = ic;
out:
VICVectAddr = 0;
}
@ -134,15 +138,16 @@ out:
// idle=0x8000 RFIFO, send what the acquisition fifos provide.
// 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;
unsigned int iflg = disable_irq(INT_DISABLE);
j->command = cmd;
j->cmd_count = cmd_size;
j->idle_count = ic;
j->count = ic;
j->read_count = rc;
ssp_frame_count = 0;
ssp_frames_sent = 0;
ssp_frames_read = 0;
enable_irq(iflg);
ssp_poll();
return 0;
@ -158,6 +163,8 @@ int ssp_submit_job(const struct ssp_job *jj)
ssp_set_buffer(0, 0);
}
memcpy((void*)&job, jj, n);
ssp_frames_sent = 0;
ssp_frames_read = 0;
enable_irq(iflg);
ssp_poll();
return 0;
@ -168,8 +175,8 @@ void ssp_reset(void)
SSPIMSC = 0;
volatile struct ssp_job *j=&job;
unsigned int iflg = disable_irq(INT_DISABLE);
j->count = 0;
j->cmd_count = 0;
j->idle_count = 0;
j->read_count = 0;
enable_irq(iflg);
}
@ -218,7 +225,7 @@ int ssp_busy(void)
volatile struct ssp_job *j=&job;
ssp_poll(); // run the isr to drain the backlog
// 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)
return c;
// Hardware is busy
@ -386,7 +393,8 @@ const struct keywords ssp_variable_names[] = {
VARIABLE("ssp_response", (void *)&ssp_lastword),
VARIABLE("ssp_match", &ssp_match),
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_config", &ssp_conf_default),
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_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_wait(int timeout);
@ -23,7 +23,8 @@ extern unsigned int ssp_idle;
extern unsigned int ssp_match_mask;
extern unsigned int ssp_match_value;
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 int (*ssp_callback)();
@ -61,23 +62,26 @@ extern struct ssp_config ssp_confs[];
#define ssp_conf_dac ssp_confs[2]
#define ssp_conf_bate ssp_confs[3]
// volatile part of the job, inaccessible globally
// volatile part of the job
// inaccessible globally
struct ssp_job {
unsigned int cmd_count;
unsigned int read_count;
unsigned int idle_count;
unsigned short cmd_count;
unsigned short read_count;
unsigned short count;
unsigned short idle_frame;
const unsigned short *command;
unsigned int buf_count;
unsigned short buf_count;
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 {
unsigned int mask;
unsigned int value;
unsigned int count;
unsigned int idle;
unsigned int size;
unsigned char frame_count;
unsigned char read_count;
unsigned short count;
unsigned short mask;
unsigned short value;
} ssp_match;
struct ssp_batch;
@ -116,23 +120,12 @@ enum ssp_batch_flags {
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.
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.size = size;
ssp_match.frame_count = count;
ssp_match.read_count = size;
}
int ssp_submit_job(const struct ssp_job *jj);