Skip to content

Commit

Permalink
swap ev3-pru0 and ev3-pru1 project
Browse files Browse the repository at this point in the history
it turns out that the existing soft-UART driver uses PRU0, so we want the tacho counter to be PRU1
  • Loading branch information
dlech committed Jul 8, 2018
1 parent 699fb87 commit b21e26b
Show file tree
Hide file tree
Showing 7 changed files with 312 additions and 312 deletions.
78 changes: 39 additions & 39 deletions ev3-pru0/.cproject

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion ev3-pru0/AM18xx_PRU.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
MEMORY
{
PAGE 0:
/* 2kB PRU0/1 Instruction RAM */
/* 4kB PRU0/1 Instruction RAM */
PRU_IMEM : org = 0x00000000 len = 0x00001000

PAGE 1:
Expand Down
162 changes: 21 additions & 141 deletions ev3-pru0/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,174 +15,54 @@

#include "resource_table.h"

/* from Linux */

#define EV3_PRU_TACHO_RING_BUF_SIZE 1024 /* must be power of 2! */

enum ev3_pru_tacho_msg_type {
/* Host >< PRU: request memory map address of ring buffer data */
EV3_PRU_TACHO_MSG_DATA_ADDR,
};

struct ev3_pru_tacho_msg {
uint32_t type;
uint32_t value;
};

enum ev3_pru_tacho {
EV3_PRU_TACHO_A,
EV3_PRU_TACHO_B,
EV3_PRU_TACHO_C,
EV3_PRU_TACHO_D,
NUM_EV3_PRU_TACHO
};

struct ev3_pru_tacho_remote_data {
uint32_t position[NUM_EV3_PRU_TACHO][EV3_PRU_TACHO_RING_BUF_SIZE];
uint32_t timestamp[NUM_EV3_PRU_TACHO][EV3_PRU_TACHO_RING_BUF_SIZE];
uint32_t head[NUM_EV3_PRU_TACHO];
};

/* end Linux */

enum direction {
REVERSE = -1,
UNKNOWN = 0,
FORWARD = 1
};

#define REMOTE_DATA_ADDR 0x80002000
#define REMOTE_DATA (*(struct ev3_pru_tacho_remote_data *)(REMOTE_DATA_ADDR))

// system events to/from ARM

// PRU0
#define HOST_INT (uint32_t)(1 << 30) // host interrupt 0
#define EVENT_FROM_ARM 32
#define EVENT_TO_ARM 33
#define EVENT_FROM_ARM 60
#define EVENT_TO_ARM 61

// PRU1
//#define HOST_INT (uint32_t)(1 << 31) // host interrupt 1
//#define EVENT_FROM_ARM 34
//#define EVENT_TO_ARM 35
//#define EVENT_FROM_ARM 62
//#define EVENT_TO_ARM 63

volatile uint32_t register __R31;

// This is 512B (RPMSG_BUF_SIZE), so it won't fit in PRU RAM, so put it in shared RAM
#define payload ((void *)(REMOTE_DATA_ADDR + sizeof(struct ev3_pru_tacho_remote_data)))

#define INTA GPIO.IN_DATA45_bit.GP5P11 // GPIO 5[11]
#define INTB GPIO.IN_DATA45_bit.GP5P8 // GPIO 5[8]
#define INTC GPIO.IN_DATA45_bit.GP5P13 // GPIO 5[13]
#define INTD GPIO.IN_DATA67_bit.GP6P9 // GPIO 6[9]

#define DIRA GPIO.IN_DATA01_bit.GP0P4 // GPIO 0[4]
#define DIRB GPIO.IN_DATA23_bit.GP2P9 // GPIO 2[9]
#define DIRC GPIO.IN_DATA23_bit.GP3P14 // GPIO 3[14]
#define DIRD GPIO.IN_DATA23_bit.GP2P8 // GPIO 2[8]

#define TACHO_STATE(x) ((INT##x << 1) | DIR##x)

static uint8_t tacho_state[NUM_EV3_PRU_TACHO];
static uint32_t tacho_prev_timestamp[NUM_EV3_PRU_TACHO];
static uint32_t tacho_counts[NUM_EV3_PRU_TACHO];

static void update_tacho_state(enum ev3_pru_tacho idx, uint8_t new_state)
{
uint8_t current_state = tacho_state[idx] & 0x3;
enum direction new_dir = UNKNOWN;
uint32_t now, elapsed;

switch (current_state) {
case 0x0:
if (new_state == 0x1) {
new_dir = REVERSE;
} else if (new_state == 0x2) {
new_dir = FORWARD;
}
break;

case 0x1:
if (new_state == 0x3) {
new_dir = REVERSE;
} else if (new_state == 0x0) {
new_dir = FORWARD;
}
break;

case 0x3:
if (new_state == 0x2) {
new_dir = REVERSE;
} else if (new_state == 0x1) {
new_dir = FORWARD;
}
break;

case 0x2:
if (new_state == 0x0) {
new_dir = REVERSE;
} else if (new_state == 0x3) {
new_dir = FORWARD;
}
break;
}

tacho_state[idx] = new_state;
tacho_counts[idx] += new_dir;
// only have 512B for stack/data, so this won't fit
//uint8_t payload[RPMSG_BUF_SIZE];
// using 128K shared RAM for now
#define payload ((uint8_t *)(0x8001F200))

now = TIMER64P0.TIM34;
elapsed = now - tacho_prev_timestamp[idx];

// if there was a change in count or if count hasn't changed for 50ms
if (new_dir || elapsed > (50 * 1000000 * 3 / 125)) {
uint32_t new_head = (REMOTE_DATA.head[idx] + 1) & (EV3_PRU_TACHO_RING_BUF_SIZE - 1);

tacho_prev_timestamp[idx] = now;

REMOTE_DATA.position[idx][new_head] = tacho_counts[idx];
REMOTE_DATA.timestamp[idx][new_head] = now;
REMOTE_DATA.head[idx] = new_head;
}
}
#define LED (GPIO.OUT_DATA67_bit.GP6P7)

int main(void) {
volatile uint8_t *status;
struct pru_rpmsg_transport transport;
uint16_t src, dst, len;

// Clear the status of the PRU-system event that the ARM will use to 'kick' us
PRU_INTC.STATIDXCLR = EVENT_FROM_ARM;
PRU_INTC.STATIDXCLR_bit.INDEX = EVENT_FROM_ARM;

// Wait until Linux gives us the OK that the driver is loaded
status = &resource_table.rpmsg_vdev.status;
while (!(*status & VIRTIO_CONFIG_S_DRIVER_OK));

pru_virtqueue_init(&transport.virtqueue0, &resource_table.vring0, EVENT_TO_ARM, EVENT_FROM_ARM);
pru_virtqueue_init(&transport.virtqueue1, &resource_table.vring1, EVENT_TO_ARM, EVENT_FROM_ARM);
pru_rpmsg_init(&transport, &resource_table.vring0, &resource_table.vring1, EVENT_TO_ARM, EVENT_FROM_ARM);

while (pru_rpmsg_channel(RPMSG_NS_CREATE, &transport, "ev3-tacho-rpmsg", 0) != PRU_RPMSG_SUCCESS);
while (pru_rpmsg_channel(RPMSG_NS_CREATE, &transport, "rpmsg-client-sample", 0) != PRU_RPMSG_SUCCESS);

while (true) {
// wait for the ARM to kick us
while (!(__R31 & HOST_INT)) {
update_tacho_state(EV3_PRU_TACHO_A, TACHO_STATE(A));
update_tacho_state(EV3_PRU_TACHO_B, TACHO_STATE(B));
update_tacho_state(EV3_PRU_TACHO_C, TACHO_STATE(C));
update_tacho_state(EV3_PRU_TACHO_D, TACHO_STATE(D));
}

// clear the interrupt
PRU_INTC.STATIDXCLR = EVENT_FROM_ARM;

// Receive all available messages, multiple messages can be sent per kick
while (pru_rpmsg_receive(&transport, &src, &dst, payload, &len) == PRU_RPMSG_SUCCESS) {
struct ev3_pru_tacho_msg *msg = payload;

switch (msg->type) {
case EV3_PRU_TACHO_MSG_DATA_ADDR:
msg->value = REMOTE_DATA_ADDR;
pru_rpmsg_send(&transport, dst, src, msg, sizeof(*msg));
break;
// Check bit 30 of register R31 to see if the ARM has kicked us
if (__R31 & HOST_INT) {
// clear the interrupt
PRU_INTC.STATIDXCLR_bit.INDEX = EVENT_FROM_ARM;

// Receive all available messages, multiple messages can be sent per kick
while (pru_rpmsg_receive(&transport, &src, &dst, payload, &len) == PRU_RPMSG_SUCCESS) {
// Echo the message back
pru_rpmsg_send(&transport, dst, src, payload, len);
}
}
}
Expand Down
53 changes: 26 additions & 27 deletions ev3-pru0/resource_table.h
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
/*
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
* Copyright (C) 2018 David Lechner <[email protected]>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

Expand All @@ -42,7 +42,7 @@
/*
* The feature bitmap for virtio rpmsg
*/
#define VIRTIO_RPMSG_F_NS 0 //name service notifications
#define VIRTIO_RPMSG_F_NS 0 //name service notifications

/* This firmware supports name service notifications as one of its features */
#define RPMSG_FEATURES (1 << VIRTIO_RPMSG_F_NS)
Expand All @@ -62,8 +62,7 @@ struct custom_resource_table {

#pragma DATA_SECTION(resource_table, ".resource_table")
#pragma RETAIN(resource_table)
struct custom_resource_table resource_table =
{
struct custom_resource_table resource_table = {
.base = {
.ver = 1,
.num = NUM_RESOURCES,
Expand All @@ -77,23 +76,23 @@ struct custom_resource_table resource_table =
.id = VIRTIO_ID_RPMSG,
.notifyid = 0,
.dfeatures = RPMSG_FEATURES,
.gfeatures = 0, //will be populated by host
.gfeatures = 0, //will be populated by host
.config_len = 0,
.status = 0,
.num_of_vrings = 2,
.reserved = { 0, 0 },
},
.vring0 = {
.da = 0, //will be populated by host
.align = 16,
.num = 16, // must be power of 2
.da = 0, //will be populated by host
.align = 16,
.num = 16, // must be power of 2
.notifyid = 0, //will be populated by host
.reserved = 0,
},
.vring1 = {
.da = 0, //will be populated by host
.align = 16,
.num = 16, // must be power of 2
.da = 0, //will be populated by host
.align = 16,
.num = 16, // must be power of 2
.notifyid = 0, //will be populated by host
.reserved = 0,
},
Expand Down
Loading

0 comments on commit b21e26b

Please sign in to comment.