/*
* This file is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
* Code by Andrew Tridgell and Siddharth Bharat Purohit
*/
#include "shared_dma.h"
/*
code to handle sharing of DMA channels between peripherals
*/
#if CH_CFG_USE_MUTEXES == TRUE && !defined(HAL_NO_SHARED_DMA)
#include
using namespace ChibiOS;
extern const AP_HAL::HAL& hal;
Shared_DMA::dma_lock Shared_DMA::locks[SHARED_DMA_MAX_STREAM_ID+1];
volatile Shared_DMA::dma_stats* Shared_DMA::_contention_stats;
void Shared_DMA::init(void)
{
for (uint8_t i=0; icontention = true;
if (_contention_stats != nullptr) {
_contention_stats[stream_id1].contended_locks++;
}
}
chSysEnable();
contention = true;
return false;
}
if (_contention_stats != nullptr && stream_id1 < SHARED_DMA_MAX_STREAM_ID) {
_contention_stats[stream_id1].uncontended_locks++;
}
if (!lock_stream_nonblocking(stream_id2)) {
unlock_stream(stream_id1, false);
chSysDisable();
if (locks[stream_id2].obj != nullptr && locks[stream_id2].obj != this) {
locks[stream_id2].obj->contention = true;
if (_contention_stats != nullptr) {
_contention_stats[stream_id2].contended_locks++;
}
}
chSysEnable();
contention = true;
return false;
}
lock_core();
if (_contention_stats != nullptr && stream_id2 < SHARED_DMA_MAX_STREAM_ID) {
_contention_stats[stream_id2].uncontended_locks++;
}
return true;
}
// unlock the DMA channels
#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wframe-larger-than=128"
void Shared_DMA::unlock(bool success)
{
osalDbgAssert(have_lock, "must have lock");
have_lock = false;
unlock_stream(stream_id2, success);
unlock_stream(stream_id1, success);
}
#pragma GCC diagnostic pop
/*
lock all channels - used on reboot to ensure no sensor DMA is in
progress
*/
void Shared_DMA::lock_all(void)
{
for (uint8_t i=0; i