aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2021-05-03 00:15:49 -0400
committerKevin O'Connor <kevin@koconnor.net>2021-10-21 01:25:17 -0400
commit92e1481a52bfe5e371b7c7d464e526d6314979c5 (patch)
treeae280478b2748fdbd98b9c399731bf6179c5e9a5 /src
parent5c10001bc525701f0ef004041cbbf093522f6de6 (diff)
downloadkutter-92e1481a52bfe5e371b7c7d464e526d6314979c5.tar.gz
kutter-92e1481a52bfe5e371b7c7d464e526d6314979c5.tar.xz
kutter-92e1481a52bfe5e371b7c7d464e526d6314979c5.zip
pru: Perform message encoding on pru0 to free space on pru1
Copy the parameters of calls to console_sendf() on pru1 to pru0 and then call that function on pru0. Although copying the parameters is a "hack", the code size reduction is notable. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src')
-rw-r--r--src/pru/internal.h8
-rw-r--r--src/pru/main.c25
-rw-r--r--src/pru/pru0.c70
3 files changed, 66 insertions, 37 deletions
diff --git a/src/pru/internal.h b/src/pru/internal.h
index dc125cd3..2aef0da3 100644
--- a/src/pru/internal.h
+++ b/src/pru/internal.h
@@ -23,16 +23,12 @@
#define ALT_PRU_PTR(ptr) ((typeof(ptr))((uint32_t)(ptr) ^ 0x2000))
// Layout of shared memory
-struct shared_response_buffer {
- uint32_t count;
- uint8_t data[MESSAGE_MAX];
-};
struct shared_mem {
uint32_t signal;
+ void *next_encoder_args;
+ uint32_t next_encoder;
const struct command_parser *next_command;
uint32_t next_command_args[16];
- uint32_t send_push_pos, send_pop_pos;
- struct shared_response_buffer send_data[4];
const struct command_parser *command_index;
uint32_t command_index_size;
const struct command_parser *shutdown_handler;
diff --git a/src/pru/main.c b/src/pru/main.c
index 37354d90..27634a12 100644
--- a/src/pru/main.c
+++ b/src/pru/main.c
@@ -1,6 +1,6 @@
// Main starting point for PRU code.
//
-// Copyright (C) 2017 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2017-2021 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU GPLv3 license.
@@ -78,6 +78,8 @@ timer_kick(void)
CT_INTC.SECR0 = 1 << IEP_EVENT;
}
+static uint32_t in_timer_dispatch;
+
static void
_irq_poll(void)
{
@@ -88,9 +90,11 @@ _irq_poll(void)
}
if (secr0 & (1 << IEP_EVENT)) {
CT_IEP.TMR_CMP_STS = 0xff;
+ in_timer_dispatch = 1;
uint32_t next = timer_dispatch_many();
timer_set(next);
CT_INTC.SECR0 = 1 << IEP_EVENT;
+ in_timer_dispatch = 0;
}
}
void __attribute__((optimize("O2")))
@@ -141,26 +145,23 @@ DECL_TASK(console_task);
void
console_sendf(const struct command_encoder *ce, va_list args)
{
- // Verify space for message
- uint32_t send_push_pos = SHARED_MEM->send_push_pos;
- struct shared_response_buffer *s = &SHARED_MEM->send_data[send_push_pos];
- if (readl(&s->count))
- return;
-
- // Generate message
- uint32_t msglen = command_encodef(s->data, ce, args);
+ SHARED_MEM->next_encoder_args = args;
+ writel(&SHARED_MEM->next_encoder, (uint32_t)ce);
// Signal PRU0 to transmit message
- writel(&s->count, msglen);
write_r31(R31_WRITE_IRQ_SELECT | (KICK_PRU0_EVENT - R31_WRITE_IRQ_OFFSET));
- SHARED_MEM->send_push_pos = (
- (send_push_pos + 1) % ARRAY_SIZE(SHARED_MEM->send_data));
+ uint32_t itd = in_timer_dispatch;
+ while (readl(&SHARED_MEM->next_encoder))
+ if (!itd)
+ irq_poll();
}
void
console_shutdown(void)
{
writel(&SHARED_MEM->next_command, 0);
+ writel(&SHARED_MEM->next_encoder, 0);
+ in_timer_dispatch = 0;
}
DECL_SHUTDOWN(console_shutdown);
diff --git a/src/pru/pru0.c b/src/pru/pru0.c
index 266b9b1f..32dd2861 100644
--- a/src/pru/pru0.c
+++ b/src/pru/pru0.c
@@ -1,6 +1,6 @@
// Code to handle IO on PRU0 and pass the messages to PRU1
//
-// Copyright (C) 2017 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2017-2021 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU GPLv3 license.
@@ -14,7 +14,7 @@
#include <pru_virtio_ids.h> // VIRTIO_ID_RPMSG
#include <rsc_types.h> // resource_table
#include "board/io.h" // readl
-#include "command.h" // command_add_frame
+#include "command.h" // command_encode_add_frame
#include "compiler.h" // __section
#include "internal.h" // SHARED_MEM
#include "sched.h" // sched_shutdown
@@ -46,14 +46,19 @@ flush_messages(void)
transmit_pos = 0;
}
-// Generate a message block and queue it for transmission
-static void
-build_message(uint8_t *msg, int msglen)
+// Verify space for a message block
+static uint8_t *
+get_transmit_ptr(const struct command_encoder *ce)
{
- if (transmit_pos + msglen > sizeof(transmit_buf))
+ if (transmit_pos + ce->max_size > sizeof(transmit_buf))
flush_messages();
- memcpy(&transmit_buf[transmit_pos], msg, msglen);
- command_add_frame(&transmit_buf[transmit_pos], msglen);
+ return &transmit_buf[transmit_pos];
+}
+
+// Finalize a message block and queue it for transmission
+static void
+finalize_transmit(int msglen)
+{
transmit_pos += msglen;
}
@@ -62,16 +67,42 @@ static void
check_can_send(void)
{
for (;;) {
- uint32_t send_pop_pos = SHARED_MEM->send_pop_pos;
- struct shared_response_buffer *s = &SHARED_MEM->send_data[send_pop_pos];
- uint32_t count = readl(&s->count);
- if (!count)
- // Queue empty
+ uint32_t rce = readl(&SHARED_MEM->next_encoder);
+ if (!rce)
break;
- build_message(s->data, count);
- writel(&s->count, 0);
- SHARED_MEM->send_pop_pos = (
- (send_pop_pos + 1) % ARRAY_SIZE(SHARED_MEM->send_data));
+ // Copy va_args on pru1 for use on pru0
+ void *pru1_args = ALT_PRU_PTR(SHARED_MEM->next_encoder_args);
+ uint32_t local_args[16];
+ memcpy(local_args, pru1_args, sizeof(local_args));
+ const struct command_encoder *pru1_ce = ALT_PRU_PTR((void*)rce);
+ struct command_encoder ce;
+ memcpy(&ce, pru1_ce, sizeof(ce));
+ if (readl(&SHARED_MEM->next_encoder) != rce)
+ continue;
+ // Fixup any pointers in va_args
+ ce.param_types = ALT_PRU_PTR(ce.param_types);
+ uint32_t pos=0, v, i, count = ce.num_params;
+ for (i=0; i<count; i++) {
+ switch (ce.param_types[i]) {
+ case PT_progmem_buffer:
+ case PT_buffer:
+ pos++;
+ // NO BREAK
+ case PT_string:
+ v = local_args[pos];
+ if (v < 0x2000)
+ // Translate pointer
+ local_args[pos] = (uint32_t)ALT_PRU_PTR((void*)v);
+ }
+ pos++;
+ }
+ // Encode and build message
+ uint8_t *data = get_transmit_ptr(&ce);
+ int msglen = command_encode_and_frame(data, &ce, (void*)local_args);
+ if (readl(&SHARED_MEM->next_encoder) != rce)
+ continue;
+ writel(&SHARED_MEM->next_encoder, 0);
+ finalize_transmit(msglen);
}
}
@@ -213,8 +244,9 @@ sched_shutdown(uint_fast8_t reason)
void
console_sendf(const struct command_encoder *ce, va_list args)
{
- uint8_t buf[MESSAGE_MIN];
- build_message(buf, sizeof(buf));
+ uint8_t *data = get_transmit_ptr(ce);
+ int msglen = command_encode_and_frame(data, ce, args);
+ finalize_transmit(msglen);
}