Mysterion
Mysterion

Reputation: 123

raspberrypi gpio interrupt rtems

I'm trying to develop an RTEMS application that decodes a message that's encoded with Manchester encoder transmitted by the transmitter board. Two Raspberry Pi 2 are mounted on the board, which are connected to each other via GPIO 4 and GND. One of the Rpi is the transmitter, and sends a sequence of pulses every 10s. These pulses encode a message according to the Manchester code. The IEEE version of the code is used. There is a promise that the first bit is a 0 bit.

I'm having trouble getting the signal. For now, I'm only trying to get the signal based on edges, but I'm not getting the signal printed.

I've been trying for 2 days but I don't really now what I'm doing wrong. Any help is greatly appreciated

#define GPIO_PIN 4
#define MAX_EDGES 4096
#define SIGNAL_GAP_MS 100

volatile int edge_count = 0;
volatile rtems_interval edge_times[MAX_EDGES];
volatile rtems_interval last_edge_time = 0;
volatile uint32_t edge_values[MAX_EDGES];
volatile bool new_signal_ready = false;

void handler(void *arg) {
  rtems_interval current_time = rtems_clock_get_ticks_since_boot();
  uint8_t value = rtems_gpio_bsp_get_value(0, GPIO_PIN);
  rtems_interval time_since_last_edge = current_time - last_edge_time;

  if (time_since_last_edge >
      rtems_clock_get_ticks_per_second() * SIGNAL_GAP_MS / 1000) {
    if (edge_count > 0) {
      new_signal_ready = true;
    }
    edge_count = 0;
  }

  if (edge_count < MAX_EDGES) {
    edge_times[edge_count] = current_time - last_edge_time;
    edge_values[edge_count] = value;

    edge_count++;
  }

  last_edge_time = current_time;
}

void init_gpio(void) {
  rtems_status_code sc;

  sc = rtems_gpio_bsp_select_input(0, GPIO_PIN, NULL);
  if (sc != RTEMS_SUCCESSFUL) {
    printk("Failed to set GPIO %d as input. Error code: %s\n", GPIO_PIN,
           rtems_status_text(sc));
    return;
  }

  sc = rtems_gpio_bsp_set_resistor_mode(0, GPIO_PIN, PULL_UP);
  if (sc != RTEMS_SUCCESSFUL) {
    printk("Failed to set pull-up resistor for GPIO %d. Error code: %s\n",
           GPIO_PIN, rtems_status_text(sc));
    return;
  }

  printk("GPIO %d initialized as input with pull-up.\n", GPIO_PIN);
}

void interrupt_config(void) {
  rtems_status_code sc;

  sc = rtems_gpio_bsp_enable_interrupt(0, GPIO_PIN, BOTH_EDGES);
  if (sc != RTEMS_SUCCESSFUL) {
    printk("Failed to enable interrupt on GPIO %d. Error code: %s\n", GPIO_PIN,
           rtems_status_text(sc));
    return;
  }

  printk("Interrupt enabled on GPIO %d.\n", GPIO_PIN);

  sc = rtems_interrupt_handler_install(rtems_gpio_bsp_get_vector(0),
                                       "GPIO Interrupt Handler",
                                       RTEMS_INTERRUPT_UNIQUE, handler, NULL);

  if (sc != RTEMS_SUCCESSFUL) {
    printk("Failed to install interrupt handler. Error code: %s\n",
           rtems_status_text(sc));
    return;
  } else {
    printk("Interrupt handler installed.\n");
  }
}

void print_signal(void) {
  printk("Signal received with %d edges:\n", edge_count);

  for (int i = 0; i < edge_count; i++) {
    printk("%d", edge_values[i]);
  }

  printk("\nEnd of signal sequence.\n\n");
}

void reset_signal_data(void) {
  edge_count = 0;
  for (int i = 0; i < MAX_EDGES; i++) {
    edge_times[i] = 0;
    edge_values[i] = 0;
  }
}

rtems_task Init(rtems_task_argument argument) {
  rtems_status_code sc;

  printk("Initializing ...\n");

  sc = rtems_gpio_initialize();
  if (sc != RTEMS_SUCCESSFUL) {
    printk("Failed to initialize GPIO. Error code: %s\n",
           rtems_status_text(sc));
    return;
  } else {
    printk("GPIO API initialized.\n");
  }

  init_gpio();
  interrupt_config();

  while (1) {
    if (new_signal_ready) {
      print_signal();
      new_signal_ready = false;
    }

    reset_signal_data();
    rtems_task_wake_after(1);
  }
}

Upvotes: 2

Views: 98

Answers (1)

Mysterion
Mysterion

Reputation: 123

Edit: I updated the code. I think it was a memory problem, #define CONFIGURE_MAXIMUM_TASKS rtems_resource_unlimited(5) did the job. You can find more informations here General System Configuration

#include <bsp.h>
#include <bsp/gpio.h>
#include <rtems.h>
#include <rtems/bspIo.h>
#include <stdint.h>

#define GPIO_PIN 4
#define GPIO_BANK 0
#define MAX_BITS 4000             // Increased to allow for longer signals
#define EDGE_THRESHOLD_NS 1000000 // 1ms in nanoseconds

volatile bool edge_detected = false;
volatile uint8_t decoded_bits[MAX_BITS / 8];
volatile uint32_t bit_count = 0;
volatile uint64_t last_edge_time = 0;

rtems_gpio_irq_state handler(void *arg) {
  (void)arg;
  edge_detected = true;
  return IRQ_HANDLED;
}

void decode_manchester(void) {
  uint64_t current_time = rtems_clock_get_uptime_nanoseconds();
  uint64_t time_diff = current_time - last_edge_time;
  decoded_bits[0] &= ~(1 << 7);
  if (time_diff > EDGE_THRESHOLD_NS) {
    uint8_t bit_value = rtems_gpio_get_value(GPIO_PIN);
    uint32_t byte_index = bit_count / 8;
    uint32_t bit_index = 7 - (bit_count % 8);

    if (byte_index < MAX_BITS / 8) {
      if (bit_value)
        decoded_bits[byte_index] |= (1 << bit_index);
      else
        decoded_bits[byte_index] &= ~(1 << bit_index);

      bit_count++;
    }

    last_edge_time = current_time;
  }
}

void print_decoded_message(void) {
  printk("Bit length: %u Bits / %u Bytes\n", bit_count, bit_count / 8);

  // Print binary
  printk("Binary:\n");
  for (uint32_t i = 0; i < (bit_count + 7) / 8; i++) {
    for (int j = 7; j >= 0; j--) {
      if (i * 8 + (7 - j) < bit_count)
        printk("%c", (decoded_bits[i] & (1 << j)) ? '1' : '0');
    }
    printk(" ");
  }
  printk("\n");

  // Print ASCII
  printk("ASCII:\n");
  for (uint32_t i = 0; i < (bit_count + 7) / 8; i++) {
    char c = decoded_bits[i];
    if (c >= 32 && c <= 126) // Printable ASCII range
      printk("%c", c);
    else
      printk(".");
  }
  printk("\n\n");

  // Reset for next signal
  bit_count = 0;
}

rtems_task Init(rtems_task_argument ignored) {
  (void)ignored;
  rtems_status_code sc;

  printk("\n*** Manchester Decoder ***\n\n");

  printk("Initializing GPIO and setting up interrupt...\n\n");

  sc = rtems_gpio_initialize();
  if (sc != RTEMS_SUCCESSFUL) {
    printk("Failed to initialize GPIO. Error: %s\n", rtems_status_text(sc));
    rtems_task_delete(RTEMS_SELF);
    return;
  } else {
    printk("GPIO initialized\n");
  }

  sc = rtems_gpio_request_pin(GPIO_PIN, DIGITAL_INPUT, false, false, NULL);
  if (sc != RTEMS_SUCCESSFUL) {
    printk("Failed to request GPIO pin. Error: %s\n", rtems_status_text(sc));
    rtems_task_delete(RTEMS_SELF);
    return;
  } else {
    printk("GPIO pin requested\n");
  }

  sc = rtems_gpio_resistor_mode(GPIO_PIN, PULL_UP);
  if (sc != RTEMS_SUCCESSFUL) {
    printk("Failed to set resistor mode. Error: %s\n", rtems_status_text(sc));
    rtems_task_delete(RTEMS_SELF);
    return;
  } else {
    printk("Pull-Up resistor enabled\n");
  }

  sc = rtems_gpio_enable_interrupt(GPIO_PIN, BOTH_EDGES, UNIQUE_HANDLER, true,
                                   handler, NULL);
  if (sc != RTEMS_SUCCESSFUL) {
    printk("Failed to enable interrupt. Error: %s\n", rtems_status_text(sc));
    rtems_task_delete(RTEMS_SELF);
    return;
  } else {
    printk("GPIO interrupt enabled\n\n");
  }

  printk("GPIO initialized. Waiting for signals...\n\n");

  while (1) {
    if (edge_detected) {
      decode_manchester();
      edge_detected = false;
    }

    if (rtems_clock_get_uptime_nanoseconds() - last_edge_time >
        500000000) { // half a second of inactivity
      if (bit_count > 0) {
        printk("Signal complete. Decoding signal...\n\n");
        print_decoded_message();
      }
    }

    rtems_task_wake_after(1); // Yield to other tasks
  }
}

#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
#define CONFIGURE_MAXIMUM_TASKS rtems_resource_unlimited(5)
#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1
#define CONFIGURE_MAXIMUM_SEMAPHORES 4
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
#define CONFIGURE_MICROSECONDS_PER_TICK 1000 // 1ms per tick
#define CONFIGURE_INIT

#include <rtems/confdefs.h>

Upvotes: 0

Related Questions