Files
lab-rv32i-c-gpio-edges-debo…/src/tasks/task04_raw_c_superloop.c
T

182 lines
6.5 KiB
C

#include "c13_common.h"
#define TASK04_GPIO_INPUT (UINT32_C(1) << 4)
#define TASK04_GPIO_EFFECT (UINT32_C(1) << 0)
#define TASK04_UART_EFFECT (UINT32_C(1) << 1)
#define TASK04_TIMER_EFFECT (UINT32_C(1) << 2)
#define TASK04_TIMER_PERIOD UINT64_C(10000)
volatile uint32_t g_task04_timer_irq_count;
volatile uint32_t g_task04_timer_flag;
volatile uint32_t g_task04_timer_mcause;
volatile uint64_t g_task04_timer_deadline;
volatile uint64_t g_task04_timer_observed;
volatile uint32_t g_task04_uart_irq_count;
volatile uint32_t g_task04_uart_irq_number;
volatile uint32_t g_task04_uart_byte;
volatile uint32_t g_task04_uart_flag;
volatile uint32_t g_task04_gpio_irq_count;
volatile uint32_t g_task04_gpio_irq_number;
volatile uint32_t g_task04_gpio_level;
volatile uint32_t g_task04_gpio_flag;
volatile uint32_t g_task04_main_timer_actions;
volatile uint32_t g_task04_main_uart_actions;
volatile uint32_t g_task04_main_gpio_actions;
volatile uint32_t g_task04_final_out;
volatile uint32_t g_task04_final_in;
volatile uint32_t g_task04_pass;
void __attribute__((interrupt("machine"))) isr_machine_timer(void)
{
const uint64_t observed = c13_timer_read64();
g_task04_timer_mcause = read_csr(mcause);
g_task04_timer_observed = observed;
g_task04_timer_deadline += TASK04_TIMER_PERIOD;
c13_timer_set_compare(g_task04_timer_deadline);
g_task04_timer_flag = 1u;
g_task04_timer_irq_count = g_task04_timer_irq_count + 1u;
}
void task04_uart_handler(void)
{
g_task04_uart_irq_number = (uint32_t)h3irq_get_current_irq();
g_task04_uart_byte = *tb_uart_reg(C13_UART_INDEX, TB_UART_DATA) & 0xffu;
g_task04_uart_flag = 1u;
g_task04_uart_irq_count = g_task04_uart_irq_count + 1u;
}
void task04_gpio_handler(void)
{
const uint32_t pending = tb_gpio_read(TB_GPIO_PENDING);
g_task04_gpio_irq_number = (uint32_t)h3irq_get_current_irq();
g_task04_gpio_level =
(tb_gpio_read(TB_GPIO_IN) & TASK04_GPIO_INPUT) != 0u;
tb_gpio_write(TB_GPIO_PENDING, pending);
g_task04_gpio_flag = 1u;
g_task04_gpio_irq_count = g_task04_gpio_irq_count + 1u;
}
static uint32_t take_flag(volatile uint32_t *flag)
{
uint32_t value;
global_irq_enable(false);
value = *flag;
*flag = 0u;
global_irq_enable(true);
return value;
}
int main(void)
{
const uint32_t output_mask =
TASK04_GPIO_EFFECT | TASK04_UART_EFFECT | TASK04_TIMER_EFFECT;
global_irq_enable(false);
timer_irq_enable(false);
external_irq_enable(false);
tb_uart_rx_irq_enable(C13_UART_INDEX, false);
h3irq_enable(C13_UART_IRQ, false);
h3irq_enable(C13_GPIO_IRQ, false);
c13_timer_set_compare(UINT64_MAX);
tb_gpio_write(TB_GPIO_DIR, output_mask);
tb_gpio_write(TB_GPIO_OUT_CLR, output_mask);
tb_gpio_write(TB_GPIO_RISE_EN, 0u);
tb_gpio_write(TB_GPIO_FALL_EN, 0u);
tb_gpio_write(TB_GPIO_PENDING, UINT32_MAX);
tb_gpio_test_set_input(0u);
h3irq_set_handler(C13_UART_IRQ, task04_uart_handler);
h3irq_set_handler(C13_GPIO_IRQ, task04_gpio_handler);
h3irq_set_priority(C13_UART_IRQ, 1u);
h3irq_set_priority(C13_GPIO_IRQ, 2u);
h3irq_enable(C13_UART_IRQ, true);
h3irq_enable(C13_GPIO_IRQ, true);
external_irq_enable(true);
tb_uart_rx_irq_enable(C13_UART_INDEX, true);
tb_gpio_write(TB_GPIO_RISE_EN, TASK04_GPIO_INPUT);
g_task04_timer_deadline = c13_timer_read64() + TASK04_TIMER_PERIOD;
c13_timer_set_compare(g_task04_timer_deadline);
timer_irq_enable(true);
global_irq_enable(true);
/* Both writes are testbench stimuli, not production peripheral registers. */
tb_uart_test_inject_rx(C13_UART_INDEX, (uint8_t)'U');
tb_gpio_test_set_input(TASK04_GPIO_INPUT);
while (g_task04_main_timer_actions == 0u ||
g_task04_main_uart_actions == 0u ||
g_task04_main_gpio_actions == 0u) {
if (take_flag(&g_task04_uart_flag) != 0u) {
if (g_task04_uart_byte == (uint32_t)'U') {
tb_gpio_write(TB_GPIO_OUT_SET, TASK04_UART_EFFECT);
}
g_task04_main_uart_actions++;
}
if (take_flag(&g_task04_gpio_flag) != 0u) {
if (g_task04_gpio_level != 0u) {
tb_gpio_write(TB_GPIO_OUT_SET, TASK04_GPIO_EFFECT);
}
g_task04_main_gpio_actions++;
}
if (take_flag(&g_task04_timer_flag) != 0u) {
tb_gpio_write(TB_GPIO_OUT_SET, TASK04_TIMER_EFFECT);
g_task04_main_timer_actions++;
}
if (g_task04_main_timer_actions == 0u ||
g_task04_main_uart_actions == 0u ||
g_task04_main_gpio_actions == 0u) {
__asm__ volatile("wfi" ::: "memory");
}
}
global_irq_enable(false);
timer_irq_enable(false);
c13_timer_set_compare(UINT64_MAX);
c13_external_disable();
tb_gpio_write(TB_GPIO_RISE_EN, 0u);
g_task04_final_out = tb_gpio_read(TB_GPIO_OUT) & output_mask;
g_task04_final_in = tb_gpio_read(TB_GPIO_IN) &
(output_mask | TASK04_GPIO_INPUT);
g_task04_pass =
g_task04_timer_irq_count == 1u &&
g_task04_timer_mcause == C13_MACHINE_TIMER_CAUSE &&
g_task04_timer_observed >= g_task04_timer_deadline - TASK04_TIMER_PERIOD &&
g_task04_uart_irq_count == 1u &&
g_task04_uart_irq_number == C13_UART_IRQ &&
g_task04_uart_byte == (uint32_t)'U' &&
g_task04_gpio_irq_count == 1u &&
g_task04_gpio_irq_number == C13_GPIO_IRQ &&
g_task04_gpio_level == 1u &&
g_task04_main_timer_actions == 1u &&
g_task04_main_uart_actions == 1u &&
g_task04_main_gpio_actions == 1u &&
g_task04_final_out == output_mask &&
g_task04_final_in == (output_mask | TASK04_GPIO_INPUT);
c13_report_u32("T04 timer_irq=", g_task04_timer_irq_count);
c13_report_u32("T04 timer_mcause=", g_task04_timer_mcause);
c13_report_u32("T04 uart_irq=", g_task04_uart_irq_count);
c13_report_u32("T04 uart_number=", g_task04_uart_irq_number);
c13_report_u32("T04 uart_byte=", g_task04_uart_byte);
c13_report_u32("T04 gpio_irq=", g_task04_gpio_irq_count);
c13_report_u32("T04 gpio_number=", g_task04_gpio_irq_number);
c13_report_u32("T04 gpio_level=", g_task04_gpio_level);
c13_report_u32("T04 main_timer=", g_task04_main_timer_actions);
c13_report_u32("T04 main_uart=", g_task04_main_uart_actions);
c13_report_u32("T04 main_gpio=", g_task04_main_gpio_actions);
c13_report_u32("T04 final_out=", g_task04_final_out);
c13_report_u32("T04 final_in=", g_task04_final_in);
c13_report_u32("T04 pass=", g_task04_pass);
return g_task04_pass ? 0 : 1;
}