Skip to content

Commit

Permalink
Changed pru interface to support halting and restarting
Browse files Browse the repository at this point in the history
  • Loading branch information
lromor committed Apr 29, 2023
1 parent 17baad1 commit eaf311e
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 27 deletions.
1 change: 1 addition & 0 deletions src/motion-queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ class PRUMotionQueue final : public MotionQueue {
bool Init();

void ClearPRUAbort(unsigned int idx);
void ClearRingBuffer();

HardwareMapping *const hardware_mapping_;
PruHardwareInterface *const pru_interface_;
Expand Down
8 changes: 8 additions & 0 deletions src/pru-hardware-interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ class PruHardwareInterface {

// Halt the PRU
virtual bool Shutdown() = 0;

// Halt any program execution. An halted program can be restarted.
virtual void Halt() = 0;

// Restart the execution of the previously halted program.
virtual void Restart() = 0;
};

class UioPrussInterface : public PruHardwareInterface {
Expand All @@ -51,6 +57,8 @@ class UioPrussInterface : public PruHardwareInterface {
bool StartExecution() final;
unsigned WaitEvent() final;
bool Shutdown() final;
void Halt() final;
void Restart() final;
};

#endif // BEAGLEG_PRU_HARDWARE_INTERFACE_
20 changes: 13 additions & 7 deletions src/pru-motion-queue.cc
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,12 @@ void PRUMotionQueue::Shutdown(bool flush_queue) {
}

bool PRUMotionQueue::Clear() {
pru_interface_->Shutdown();
return Init();
MotorEnable(false);
pru_interface_->Halt();
ClearRingBuffer();
queue_pos_ = 0;
pru_interface_->Restart();
return true;
}

PRUMotionQueue::~PRUMotionQueue() {}
Expand All @@ -192,18 +196,20 @@ PRUMotionQueue::PRUMotionQueue(HardwareMapping *hw, PruHardwareInterface *pru)
assert(success);
}

void PRUMotionQueue::ClearRingBuffer() {
for (int i = 0; i < QUEUE_LEN; ++i) {
pru_data_->ring_buffer[i].state = STATE_EMPTY;
}
}

bool PRUMotionQueue::Init() {
MotorEnable(false); // motors off initially.
if (!pru_interface_->Init()) return false;

if (!pru_interface_->AllocateSharedMem((void **)&pru_data_,
sizeof(*pru_data_)))
return false;

for (int i = 0; i < QUEUE_LEN; ++i) {
pru_data_->ring_buffer[i].state = STATE_EMPTY;
}
ClearRingBuffer();
queue_pos_ = 0;

return pru_interface_->StartExecution();
}
35 changes: 15 additions & 20 deletions src/pru-motion-queue_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
#include "pru-hardware-interface.h"
#include "segment-queue.h"

using ::testing::NiceMock;

// PRU-side mock implementation of the ring buffer.
struct MockPRUCommunication {
internal::QueueStatus status;
Expand All @@ -28,17 +26,16 @@ struct MockPRUCommunication {

class MockPRUInterface : public PruHardwareInterface {
public:
MockPRUInterface() : execution_index_(QUEUE_LEN - 1) {
mmap = NULL;
ON_CALL(*this, Init).WillByDefault([]() { return true; });
ON_CALL(*this, Shutdown).WillByDefault([]() { return true; });
}
MockPRUInterface() : execution_index_(QUEUE_LEN - 1) { mmap = NULL; }
~MockPRUInterface() override { free(mmap); }

bool Init() final { return true; }
bool StartExecution() final { return true; }
unsigned WaitEvent() final { return 1; }
MOCK_METHOD(bool, Init, (), ());
MOCK_METHOD(bool, Shutdown, (), ());
bool Shutdown() final { return true; }

MOCK_METHOD(void, Halt, (), (final));
MOCK_METHOD(void, Restart, (), (final));

bool AllocateSharedMem(void **pru_mmap, const size_t size) final {
if (mmap != NULL) return true;
Expand Down Expand Up @@ -70,15 +67,15 @@ class MockPRUInterface : public PruHardwareInterface {

TEST(PruMotionQueue, status_init) {
MotorsRegister absolute_pos_loops;
NiceMock<MockPRUInterface> pru_interface;
MockPRUInterface pru_interface;
HardwareMapping hmap = HardwareMapping();
PRUMotionQueue motion_backend(&hmap, (PruHardwareInterface *)&pru_interface);
EXPECT_EQ(motion_backend.GetPendingElements(NULL), 0);
}

TEST(PruMotionQueue, single_exec) {
MotorsRegister absolute_pos_loops;
NiceMock<MockPRUInterface> pru_interface;
MockPRUInterface pru_interface;
HardwareMapping hmap = HardwareMapping();
PRUMotionQueue motion_backend(&hmap, (PruHardwareInterface *)&pru_interface);

Expand All @@ -91,7 +88,7 @@ TEST(PruMotionQueue, single_exec) {

TEST(PruMotionQueue, full_exec) {
MotorsRegister absolute_pos_loops;
NiceMock<MockPRUInterface> pru_interface;
MockPRUInterface pru_interface;
HardwareMapping hmap = HardwareMapping();
PRUMotionQueue motion_backend(&hmap, (PruHardwareInterface *)&pru_interface);

Expand All @@ -104,7 +101,7 @@ TEST(PruMotionQueue, full_exec) {

TEST(PruMotionQueue, single_exec_some_loops) {
MotorsRegister absolute_pos_loops;
NiceMock<MockPRUInterface> pru_interface;
MockPRUInterface pru_interface;
HardwareMapping hmap = HardwareMapping();
PRUMotionQueue motion_backend(&hmap, (PruHardwareInterface *)&pru_interface);

Expand All @@ -119,7 +116,7 @@ TEST(PruMotionQueue, single_exec_some_loops) {

TEST(PruMotionQueue, one_round_queue) {
MotorsRegister absolute_pos_loops;
NiceMock<MockPRUInterface> pru_interface;
MockPRUInterface pru_interface;
HardwareMapping hmap = HardwareMapping();
PRUMotionQueue motion_backend(&hmap, (PruHardwareInterface *)&pru_interface);

Expand All @@ -141,7 +138,7 @@ TEST(PruMotionQueue, one_round_queue) {
// Check the PRU is reset and no elements are pending.
TEST(PruMotionQueue, clear_queue) {
MotorsRegister absolute_pos_loops;
NiceMock<MockPRUInterface> pru_interface;
MockPRUInterface pru_interface;
HardwareMapping hmap = HardwareMapping();
PRUMotionQueue motion_backend(&hmap, (PruHardwareInterface *)&pru_interface);

Expand All @@ -157,18 +154,16 @@ TEST(PruMotionQueue, clear_queue) {
ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&pru_interface));
{
testing::InSequence seq;
EXPECT_CALL(pru_interface, Shutdown())
.Times(1)
.WillRepeatedly(testing::Return(true));
EXPECT_CALL(pru_interface, Init()).Times(1).WillOnce(testing::Return(true));
EXPECT_CALL(pru_interface, Halt()).Times(1);
EXPECT_CALL(pru_interface, Restart()).Times(1);
}
EXPECT_TRUE(motion_backend.Clear());
EXPECT_EQ(motion_backend.GetPendingElements(NULL), 0);
}

TEST(PruMotionQueue, exec_index_lt_queue_pos) {
MotorsRegister absolute_pos_loops;
NiceMock<MockPRUInterface> pru_interface;
MockPRUInterface pru_interface;
HardwareMapping hmap = HardwareMapping();
PRUMotionQueue motion_backend(&hmap, (PruHardwareInterface *)&pru_interface);

Expand Down
4 changes: 4 additions & 0 deletions src/uio-pruss-interface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ unsigned UioPrussInterface::WaitEvent() {
return num_events;
}

void UioPrussInterface::Halt() { prussdrv_pru_disable(PRU_NUM); }

void UioPrussInterface::Restart() { prussdrv_pru_enable_at(PRU_NUM, 0); }

bool UioPrussInterface::Shutdown() {
prussdrv_pru_disable(PRU_NUM);
prussdrv_exit();
Expand Down

0 comments on commit eaf311e

Please sign in to comment.