mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-15 19:43:35 +08:00
platform: restructure (NuttX) architecture-specific code
updated: tone_alarm, px4io_serial, px4_micro_hal
This commit is contained in:
@@ -1,36 +0,0 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2015-2019 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. 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
|
||||
# distribution.
|
||||
# 3. Neither the name PX4 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
|
||||
# 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 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
px4_add_library(tone_alarm_interface
|
||||
ToneAlarmInterface.cpp
|
||||
)
|
||||
@@ -1,184 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2017-2019 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 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
|
||||
* 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 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file ToneAlarmInterface.cpp
|
||||
*/
|
||||
|
||||
#include "chip/kinetis_sim.h"
|
||||
#include "kinetis_tpm.h"
|
||||
|
||||
#include <drivers/device/device.h>
|
||||
#include <lib/drivers/tone_alarm/ToneAlarmInterface.h>
|
||||
#include <px4_defines.h>
|
||||
#include <systemlib/px4_macros.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#define CAT3_(A, B, C) A##B##C
|
||||
#define CAT3(A, B, C) CAT3_(A, B, C)
|
||||
|
||||
/* Check that tone alarm and HRT timers are different */
|
||||
#if defined(TONE_ALARM_TIMER) && defined(HRT_TIMER)
|
||||
# if TONE_ALARM_TIMER == HRT_TIMER
|
||||
# error TONE_ALARM_TIMER and HRT_TIMER must use different timers.
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef TONE_ALARM_CLOCK
|
||||
#define TONE_ALARM_CLOCK (BOARD_TPM_FREQ/(1 << (TONE_ALARM_TIMER_PRESCALE >> TPM_SC_PS_SHIFT)))
|
||||
#endif
|
||||
|
||||
/* Period of the free-running counter, in microseconds. */
|
||||
#ifndef TONE_ALARM_COUNTER_PERIOD
|
||||
#define TONE_ALARM_COUNTER_PERIOD 65536
|
||||
#endif
|
||||
|
||||
/* Tone Alarm configuration */
|
||||
#define TONE_ALARM_SIM_SCGC2_TPM CAT(SIM_SCGC2_TPM, TONE_ALARM_TIMER) /* The Clock Gating enable bit for this TPM */
|
||||
#define TONE_ALARM_TIMER_BASE CAT(CAT(KINETIS_TPM, TONE_ALARM_TIMER),_BASE) /* The Base address of the TPM */
|
||||
#define TONE_ALARM_TIMER_CLOCK BOARD_TPM_FREQ /* The input clock frequency to the TPM block */
|
||||
#define TONE_ALARM_TIMER_PRESCALE TPM_SC_PS_DIV16 /* The constant Prescaler */
|
||||
#define TONE_ALARM_TIMER_VECTOR CAT(KINETIS_IRQ_TPM, TONE_ALARM_TIMER) /* The TPM Interrupt vector */
|
||||
|
||||
#if TONE_ALARM_TIMER == 1 && defined(CONFIG_KINETIS_TPM1)
|
||||
# error must not set CONFIG_KINETIS_TPM1=y and TONE_ALARM_TIMER=1
|
||||
#elif TONE_ALARM_TIMER == 2 && defined(CONFIG_KINETIS_TPM2)
|
||||
# error must not set CONFIG_STM32_TIM2=y and TONE_ALARM_TIMER=2
|
||||
#endif
|
||||
|
||||
/* Tone Alarm clock must be a multiple of 1MHz greater than 1MHz. */
|
||||
#if (TONE_ALARM_TIMER_CLOCK % TONE_ALARM_CLOCK) != 0
|
||||
# error TONE_ALARM_TIMER_CLOCK must be a multiple of 1MHz
|
||||
#endif
|
||||
#if TONE_ALARM_TIMER_CLOCK <= TONE_ALARM_CLOCK
|
||||
# error TONE_ALARM_TIMER_CLOCK must be greater than 1MHz
|
||||
#endif
|
||||
|
||||
#if (TONE_ALARM_CHANNEL != 0) && (TONE_ALARM_CHANNEL != 1)
|
||||
# error TONE_ALARM_CHANNEL must be a value between 0 and 1
|
||||
#endif
|
||||
|
||||
|
||||
/* Register accessors */
|
||||
#define _REG(_addr) (*(volatile uint32_t *)(_addr))
|
||||
|
||||
/* Timer register accessors */
|
||||
#define REG(_reg) _REG(TONE_ALARM_TIMER_BASE + (_reg))
|
||||
|
||||
#define rC0SC REG(KINETIS_TPM_C0SC_OFFSET)
|
||||
#define rC0V REG(KINETIS_TPM_C0V_OFFSET)
|
||||
#define rC1SC REG(KINETIS_TPM_C1SC_OFFSET)
|
||||
#define rC1V REG(KINETIS_TPM_C1V_OFFSET)
|
||||
#define rCNT REG(KINETIS_TPM_CNT_OFFSET)
|
||||
#define rCOMBINE REG(KINETIS_TPM_COMBINE_OFFSET)
|
||||
#define rCONF REG(KINETIS_TPM_CONF_OFFSET)
|
||||
#define rFILTER REG(KINETIS_TPM_FILTER_OFFSET)
|
||||
#define rMOD REG(KINETIS_TPM_MOD_OFFSET)
|
||||
#define rPOL REG(KINETIS_TPM_POL_OFFSET)
|
||||
#define rQDCTRL REG(KINETIS_TPM_QDCTRL_OFFSET)
|
||||
#define rSC REG(KINETIS_TPM_SC_OFFSET)
|
||||
#define rSTATUS REG(KINETIS_TPM_STATUS_OFFSET)
|
||||
|
||||
/* Specific registers and bits used by Tone Alarm sub-functions. */
|
||||
# define rCNV CAT3(rC, TONE_ALARM_CHANNEL, V) /* Channel Value Register used by Tone alarm */
|
||||
# define rCNSC CAT3(rC, TONE_ALARM_CHANNEL, SC) /* Channel Status and Control Register used by Tone alarm */
|
||||
# define STATUS CAT3(TPM_STATUS_CH, TONE_ALARM_CHANNEL, F) /* Capture and Compare Status Register used by Tone alarm */
|
||||
|
||||
void ToneAlarmInterface::init()
|
||||
{
|
||||
#ifdef GPIO_TONE_ALARM_NEG
|
||||
px4_arch_configgpio(GPIO_TONE_ALARM_NEG);
|
||||
#else
|
||||
// Configure the GPIO to the idle state.
|
||||
px4_arch_configgpio(GPIO_TONE_ALARM_IDLE);
|
||||
#endif
|
||||
|
||||
// Select a the clock source to the TPM.
|
||||
uint32_t regval = _REG(KINETIS_SIM_SOPT2);
|
||||
|
||||
regval &= ~(SIM_SOPT2_TPMSRC_MASK);
|
||||
regval |= BOARD_TPM_CLKSRC;
|
||||
|
||||
_REG(KINETIS_SIM_SOPT2) = regval;
|
||||
|
||||
// Enabled System Clock Gating Control for TPM.
|
||||
regval = _REG(KINETIS_SIM_SCGC2);
|
||||
regval |= TONE_ALARM_SIM_SCGC2_TPM;
|
||||
_REG(KINETIS_SIM_SCGC2) = regval;
|
||||
|
||||
// Disable and configure the timer.
|
||||
rSC = TPM_SC_TOF;
|
||||
rCNT = 0;
|
||||
rMOD = TONE_ALARM_COUNTER_PERIOD - 1;
|
||||
rSTATUS = (TPM_STATUS_TOF | STATUS);
|
||||
|
||||
// Configure for output compare to toggle on over flow.
|
||||
rCNSC = (TPM_CnSC_CHF | TPM_CnSC_MSA | TPM_CnSC_ELSA);
|
||||
|
||||
rCOMBINE = 0;
|
||||
rPOL = 0;
|
||||
rFILTER = 0;
|
||||
rQDCTRL = 0;
|
||||
rCONF = TPM_CONF_DBGMODE_CONT;
|
||||
|
||||
rCNV = 0; // Toggle the CC output each time the count passes 0.
|
||||
rSC |= (TPM_SC_CMOD_LPTPM_CLK | TONE_ALARM_TIMER_PRESCALE); // Enable the timer.
|
||||
rMOD = 0; // Default the timer to a modulo value of 1; playing notes will change this.
|
||||
}
|
||||
|
||||
void ToneAlarmInterface::start_note(unsigned frequency)
|
||||
{
|
||||
// Calculate the signal switching period.
|
||||
// (Signal switching period is one half of the frequency period).
|
||||
float signal_period = (1.0f / frequency) * 0.5f;
|
||||
|
||||
// Calculate the hardware clock divisor rounded to the nearest integer.
|
||||
unsigned int divisor = std::round(signal_period * TONE_ALARM_CLOCK);
|
||||
|
||||
rCNT = 0;
|
||||
rMOD = divisor; // Load new signal switching period.
|
||||
rSC |= (TPM_SC_CMOD_LPTPM_CLK);
|
||||
|
||||
// Configure the GPIO to enable timer output.
|
||||
px4_arch_configgpio(GPIO_TONE_ALARM);
|
||||
}
|
||||
|
||||
void ToneAlarmInterface::stop_note()
|
||||
{
|
||||
// Stop the current note.
|
||||
rSC &= ~TPM_SC_CMOD_MASK;
|
||||
|
||||
// Ensure the GPIO is not driving the speaker.
|
||||
px4_arch_configgpio(GPIO_TONE_ALARM_IDLE);
|
||||
}
|
||||
@@ -38,11 +38,10 @@ px4_add_module(
|
||||
-Wno-cast-align # TODO: fix and enable
|
||||
SRCS
|
||||
px4io.cpp
|
||||
px4io_uploader.cpp
|
||||
px4io_serial.cpp
|
||||
px4io_serial_f4.cpp
|
||||
px4io_serial_f7.cpp
|
||||
px4io_uploader.cpp
|
||||
DEPENDS
|
||||
arch_px4io_serial
|
||||
circuit_breaker
|
||||
mixer
|
||||
)
|
||||
|
||||
@@ -39,14 +39,14 @@
|
||||
|
||||
#include "px4io_driver.h"
|
||||
|
||||
#include "px4io_serial.h"
|
||||
#include <px4io_serial/arch_px4io_serial.h>
|
||||
|
||||
static PX4IO_serial *g_interface;
|
||||
|
||||
device::Device
|
||||
*PX4IO_serial_interface()
|
||||
{
|
||||
return new PX4IO_INTERFACE_CLASS();
|
||||
return new ArchPX4IOSerial();
|
||||
}
|
||||
|
||||
PX4IO_serial::PX4IO_serial() :
|
||||
|
||||
@@ -1,260 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2015 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 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
|
||||
* 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 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file px4io_driver.h
|
||||
*
|
||||
* Interface for PX4IO
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/* XXX trim includes */
|
||||
#include <px4_config.h>
|
||||
#include <px4_posix.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
#include <perf/perf_counter.h>
|
||||
|
||||
#include <board_config.h>
|
||||
|
||||
#include <drivers/device/device.h>
|
||||
#include <modules/px4iofirmware/protocol.h>
|
||||
|
||||
class PX4IO_serial : public device::Device
|
||||
{
|
||||
public:
|
||||
PX4IO_serial();
|
||||
virtual ~PX4IO_serial();
|
||||
|
||||
virtual int init() = 0;
|
||||
virtual int read(unsigned offset, void *data, unsigned count = 1);
|
||||
virtual int write(unsigned address, void *data, unsigned count = 1);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Does the PX4IO_serial instance initialization.
|
||||
* @param io_buffer The IO buffer that should be used for transfers.
|
||||
* @return 0 on success.
|
||||
*/
|
||||
int init(IOPacket *io_buffer);
|
||||
|
||||
/**
|
||||
* Start the transaction with IO and wait for it to complete.
|
||||
*/
|
||||
virtual int _bus_exchange(IOPacket *_packet) = 0;
|
||||
|
||||
/**
|
||||
* Performance counters.
|
||||
*/
|
||||
perf_counter_t _pc_txns;
|
||||
perf_counter_t _pc_retries;
|
||||
perf_counter_t _pc_timeouts;
|
||||
perf_counter_t _pc_crcerrs;
|
||||
perf_counter_t _pc_protoerrs;
|
||||
perf_counter_t _pc_uerrs;
|
||||
perf_counter_t _pc_idle;
|
||||
perf_counter_t _pc_badidle;
|
||||
private:
|
||||
/*
|
||||
* XXX tune this value
|
||||
*
|
||||
* At 1.5Mbps each register takes 13.3µs, and we always transfer a full packet.
|
||||
* Packet overhead is 26µs for the four-byte header.
|
||||
*
|
||||
* 32 registers = 451µs
|
||||
*
|
||||
* Maybe we can just send smaller packets (e.g. 8 regs) and loop for larger (less common)
|
||||
* transfers? Could cause issues with any regs expecting to be written atomically...
|
||||
*/
|
||||
IOPacket *_io_buffer_ptr;
|
||||
|
||||
/** bus-ownership lock */
|
||||
px4_sem_t _bus_semaphore;
|
||||
|
||||
/* do not allow top copying this class */
|
||||
PX4IO_serial(PX4IO_serial &);
|
||||
PX4IO_serial &operator = (const PX4IO_serial &);
|
||||
};
|
||||
|
||||
#if defined(CONFIG_STM32_STM32F10XX) || defined(CONFIG_STM32_STM32F4XXX)
|
||||
/** XXX use F4 implementation for F1 as well. **/
|
||||
|
||||
#define PX4IO_INTERFACE_CLASS PX4IO_serial_f4
|
||||
#define PX4IO_INTERFACE_F4
|
||||
|
||||
class PX4IO_serial_f4 : public PX4IO_serial
|
||||
{
|
||||
public:
|
||||
PX4IO_serial_f4();
|
||||
~PX4IO_serial_f4();
|
||||
|
||||
virtual int init();
|
||||
virtual int ioctl(unsigned operation, unsigned &arg);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Start the transaction with IO and wait for it to complete.
|
||||
*/
|
||||
int _bus_exchange(IOPacket *_packet);
|
||||
|
||||
private:
|
||||
DMA_HANDLE _tx_dma;
|
||||
DMA_HANDLE _rx_dma;
|
||||
|
||||
IOPacket *_current_packet;
|
||||
|
||||
/** saved DMA status */
|
||||
static const unsigned _dma_status_inactive = 0x80000000; // low bits overlap DMA_STATUS_* values
|
||||
static const unsigned _dma_status_waiting = 0x00000000;
|
||||
volatile unsigned _rx_dma_status;
|
||||
|
||||
/** client-waiting lock/signal */
|
||||
px4_sem_t _completion_semaphore;
|
||||
|
||||
/**
|
||||
* DMA completion handler.
|
||||
*/
|
||||
static void _dma_callback(DMA_HANDLE handle, uint8_t status, void *arg);
|
||||
void _do_rx_dma_callback(unsigned status);
|
||||
|
||||
/**
|
||||
* Serial interrupt handler.
|
||||
*/
|
||||
static int _interrupt(int vector, void *context, void *arg);
|
||||
void _do_interrupt();
|
||||
|
||||
/**
|
||||
* Cancel any DMA in progress with an error.
|
||||
*/
|
||||
void _abort_dma();
|
||||
|
||||
/**
|
||||
* Performance counters.
|
||||
*/
|
||||
perf_counter_t _pc_dmasetup;
|
||||
perf_counter_t _pc_dmaerrs;
|
||||
|
||||
/* do not allow top copying this class */
|
||||
PX4IO_serial_f4(PX4IO_serial_f4 &);
|
||||
PX4IO_serial_f4 &operator = (const PX4IO_serial_f4 &);
|
||||
|
||||
/**
|
||||
* IO Buffer storage
|
||||
*/
|
||||
static IOPacket _io_buffer_storage; // XXX static to ensure DMA-able memory
|
||||
};
|
||||
|
||||
#elif defined(CONFIG_ARCH_CHIP_STM32F7)
|
||||
|
||||
#define PX4IO_INTERFACE_CLASS PX4IO_serial_f7
|
||||
#define PX4IO_INTERFACE_F7
|
||||
|
||||
#include <stm32_dma.h>
|
||||
|
||||
|
||||
class PX4IO_serial_f7 : public PX4IO_serial
|
||||
{
|
||||
public:
|
||||
PX4IO_serial_f7();
|
||||
~PX4IO_serial_f7();
|
||||
|
||||
virtual int init();
|
||||
virtual int ioctl(unsigned operation, unsigned &arg);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Start the transaction with IO and wait for it to complete.
|
||||
*/
|
||||
int _bus_exchange(IOPacket *_packet);
|
||||
|
||||
private:
|
||||
DMA_HANDLE _tx_dma;
|
||||
DMA_HANDLE _rx_dma;
|
||||
|
||||
IOPacket *_current_packet;
|
||||
|
||||
/** saved DMA status */
|
||||
static const unsigned _dma_status_inactive = 0x80000000; // low bits overlap DMA_STATUS_* values
|
||||
static const unsigned _dma_status_waiting = 0x00000000;
|
||||
volatile unsigned _rx_dma_status;
|
||||
|
||||
/** client-waiting lock/signal */
|
||||
px4_sem_t _completion_semaphore;
|
||||
|
||||
/**
|
||||
* DMA completion handler.
|
||||
*/
|
||||
static void _dma_callback(DMA_HANDLE handle, uint8_t status, void *arg);
|
||||
void _do_rx_dma_callback(unsigned status);
|
||||
|
||||
/**
|
||||
* Serial interrupt handler.
|
||||
*/
|
||||
static int _interrupt(int vector, void *context, void *arg);
|
||||
void _do_interrupt();
|
||||
|
||||
/**
|
||||
* Cancel any DMA in progress with an error.
|
||||
*/
|
||||
void _abort_dma();
|
||||
|
||||
/**
|
||||
* Performance counters.
|
||||
*/
|
||||
perf_counter_t _pc_dmasetup;
|
||||
perf_counter_t _pc_dmaerrs;
|
||||
|
||||
/* do not allow top copying this class */
|
||||
PX4IO_serial_f7(PX4IO_serial_f7 &);
|
||||
PX4IO_serial_f7 &operator = (const PX4IO_serial_f7 &);
|
||||
|
||||
/**
|
||||
* IO Buffer storage
|
||||
*/
|
||||
static uint8_t _io_buffer_storage[] __attribute__((aligned(ARMV7M_DCACHE_LINESIZE)));
|
||||
};
|
||||
|
||||
#else
|
||||
#error "Interface not implemented for this chip"
|
||||
#endif
|
||||
@@ -1,474 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2013-2015 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 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
|
||||
* 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 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file px4io_serial_f4.cpp
|
||||
*
|
||||
* Serial interface for PX4IO on STM32F4
|
||||
*/
|
||||
|
||||
#include "px4io_serial.h"
|
||||
|
||||
#ifdef PX4IO_INTERFACE_F4
|
||||
|
||||
/* serial register accessors */
|
||||
#define REG(_x) (*(volatile uint32_t *)(PX4IO_SERIAL_BASE + _x))
|
||||
#define rSR REG(STM32_USART_SR_OFFSET)
|
||||
#define rDR REG(STM32_USART_DR_OFFSET)
|
||||
#define rBRR REG(STM32_USART_BRR_OFFSET)
|
||||
#define rCR1 REG(STM32_USART_CR1_OFFSET)
|
||||
#define rCR2 REG(STM32_USART_CR2_OFFSET)
|
||||
#define rCR3 REG(STM32_USART_CR3_OFFSET)
|
||||
#define rGTPR REG(STM32_USART_GTPR_OFFSET)
|
||||
|
||||
IOPacket PX4IO_serial_f4::_io_buffer_storage;
|
||||
|
||||
PX4IO_serial_f4::PX4IO_serial_f4() :
|
||||
_tx_dma(nullptr),
|
||||
_rx_dma(nullptr),
|
||||
_current_packet(nullptr),
|
||||
_rx_dma_status(_dma_status_inactive),
|
||||
_completion_semaphore(SEM_INITIALIZER(0)),
|
||||
#if 0
|
||||
_pc_dmasetup(perf_alloc(PC_ELAPSED, "io_dmasetup ")),
|
||||
_pc_dmaerrs(perf_alloc(PC_COUNT, "io_dmaerrs "))
|
||||
#else
|
||||
_pc_dmasetup(nullptr),
|
||||
_pc_dmaerrs(nullptr)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
PX4IO_serial_f4::~PX4IO_serial_f4()
|
||||
{
|
||||
if (_tx_dma != nullptr) {
|
||||
stm32_dmastop(_tx_dma);
|
||||
stm32_dmafree(_tx_dma);
|
||||
}
|
||||
|
||||
if (_rx_dma != nullptr) {
|
||||
stm32_dmastop(_rx_dma);
|
||||
stm32_dmafree(_rx_dma);
|
||||
}
|
||||
|
||||
/* reset the UART */
|
||||
rCR1 = 0;
|
||||
rCR2 = 0;
|
||||
rCR3 = 0;
|
||||
|
||||
/* detach our interrupt handler */
|
||||
up_disable_irq(PX4IO_SERIAL_VECTOR);
|
||||
irq_detach(PX4IO_SERIAL_VECTOR);
|
||||
|
||||
/* restore the GPIOs */
|
||||
px4_arch_unconfiggpio(PX4IO_SERIAL_TX_GPIO);
|
||||
px4_arch_unconfiggpio(PX4IO_SERIAL_RX_GPIO);
|
||||
|
||||
/* Disable APB clock for the USART peripheral */
|
||||
modifyreg32(PX4IO_SERIAL_RCC_REG, PX4IO_SERIAL_RCC_EN, 0);
|
||||
|
||||
/* and kill our semaphores */
|
||||
px4_sem_destroy(&_completion_semaphore);
|
||||
|
||||
perf_free(_pc_dmasetup);
|
||||
perf_free(_pc_dmaerrs);
|
||||
}
|
||||
|
||||
int
|
||||
PX4IO_serial_f4::init()
|
||||
{
|
||||
/* initialize base implementation */
|
||||
int r;
|
||||
|
||||
if ((r = PX4IO_serial::init(&_io_buffer_storage)) != 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* allocate DMA */
|
||||
_tx_dma = stm32_dmachannel(PX4IO_SERIAL_TX_DMAMAP);
|
||||
_rx_dma = stm32_dmachannel(PX4IO_SERIAL_RX_DMAMAP);
|
||||
|
||||
if ((_tx_dma == nullptr) || (_rx_dma == nullptr)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Enable the APB clock for the USART peripheral */
|
||||
modifyreg32(PX4IO_SERIAL_RCC_REG, 0, PX4IO_SERIAL_RCC_EN);
|
||||
|
||||
/* configure pins for serial use */
|
||||
px4_arch_configgpio(PX4IO_SERIAL_TX_GPIO);
|
||||
px4_arch_configgpio(PX4IO_SERIAL_RX_GPIO);
|
||||
|
||||
/* reset & configure the UART */
|
||||
rCR1 = 0;
|
||||
rCR2 = 0;
|
||||
rCR3 = 0;
|
||||
|
||||
/* eat any existing interrupt status */
|
||||
(void)rSR;
|
||||
(void)rDR;
|
||||
|
||||
|
||||
/* configure line speed */
|
||||
uint32_t usartdiv32 = PX4IO_SERIAL_CLOCK / (PX4IO_SERIAL_BITRATE / 2);
|
||||
uint32_t mantissa = usartdiv32 >> 5;
|
||||
uint32_t fraction = (usartdiv32 - (mantissa << 5) + 1) >> 1;
|
||||
rBRR = (mantissa << USART_BRR_MANT_SHIFT) | (fraction << USART_BRR_FRAC_SHIFT);
|
||||
|
||||
/* attach serial interrupt handler */
|
||||
irq_attach(PX4IO_SERIAL_VECTOR, _interrupt, this);
|
||||
up_enable_irq(PX4IO_SERIAL_VECTOR);
|
||||
|
||||
/* enable UART in DMA mode, enable error and line idle interrupts */
|
||||
rCR3 = USART_CR3_EIE;
|
||||
|
||||
rCR1 = USART_CR1_RE | USART_CR1_TE | USART_CR1_UE | USART_CR1_IDLEIE;
|
||||
|
||||
/* create semaphores */
|
||||
px4_sem_init(&_completion_semaphore, 0, 0);
|
||||
|
||||
/* _completion_semaphore use case is a signal */
|
||||
|
||||
px4_sem_setprotocol(&_completion_semaphore, SEM_PRIO_NONE);
|
||||
|
||||
/* XXX this could try talking to IO */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PX4IO_serial_f4::ioctl(unsigned operation, unsigned &arg)
|
||||
{
|
||||
switch (operation) {
|
||||
|
||||
case 1: /* XXX magic number - test operation */
|
||||
switch (arg) {
|
||||
case 0:
|
||||
syslog(LOG_INFO, "test 0\n");
|
||||
|
||||
/* kill DMA, this is a PIO test */
|
||||
stm32_dmastop(_tx_dma);
|
||||
stm32_dmastop(_rx_dma);
|
||||
rCR3 &= ~(USART_CR3_DMAR | USART_CR3_DMAT);
|
||||
|
||||
for (;;) {
|
||||
while (!(rSR & USART_SR_TXE))
|
||||
;
|
||||
|
||||
rDR = 0x55;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case 1: {
|
||||
unsigned fails = 0;
|
||||
|
||||
for (unsigned count = 0;; count++) {
|
||||
uint16_t value = count & 0xffff;
|
||||
|
||||
if (write((PX4IO_PAGE_TEST << 8) | PX4IO_P_TEST_LED, &value, 1) != 0) {
|
||||
fails++;
|
||||
}
|
||||
|
||||
if (count >= 5000) {
|
||||
syslog(LOG_INFO, "==== test 1 : %u failures ====\n", fails);
|
||||
perf_print_counter(_pc_txns);
|
||||
perf_print_counter(_pc_dmasetup);
|
||||
perf_print_counter(_pc_retries);
|
||||
perf_print_counter(_pc_timeouts);
|
||||
perf_print_counter(_pc_crcerrs);
|
||||
perf_print_counter(_pc_dmaerrs);
|
||||
perf_print_counter(_pc_protoerrs);
|
||||
perf_print_counter(_pc_uerrs);
|
||||
perf_print_counter(_pc_idle);
|
||||
perf_print_counter(_pc_badidle);
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case 2:
|
||||
syslog(LOG_INFO, "test 2\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
PX4IO_serial_f4::_bus_exchange(IOPacket *_packet)
|
||||
{
|
||||
_current_packet = _packet;
|
||||
|
||||
/* clear any lingering error status */
|
||||
(void)rSR;
|
||||
(void)rDR;
|
||||
|
||||
/* start RX DMA */
|
||||
perf_begin(_pc_txns);
|
||||
perf_begin(_pc_dmasetup);
|
||||
|
||||
/* DMA setup time ~3µs */
|
||||
_rx_dma_status = _dma_status_waiting;
|
||||
|
||||
/*
|
||||
* Note that we enable circular buffer mode as a workaround for
|
||||
* there being no API to disable the DMA FIFO. We need direct mode
|
||||
* because otherwise when the line idle interrupt fires there
|
||||
* will be packet bytes still in the DMA FIFO, and we will assume
|
||||
* that the idle was spurious.
|
||||
*
|
||||
* XXX this should be fixed with a NuttX change.
|
||||
*/
|
||||
stm32_dmasetup(
|
||||
_rx_dma,
|
||||
PX4IO_SERIAL_BASE + STM32_USART_DR_OFFSET,
|
||||
reinterpret_cast<uint32_t>(_current_packet),
|
||||
sizeof(*_current_packet),
|
||||
DMA_SCR_CIRC | /* XXX see note above */
|
||||
DMA_SCR_DIR_P2M |
|
||||
DMA_SCR_MINC |
|
||||
DMA_SCR_PSIZE_8BITS |
|
||||
DMA_SCR_MSIZE_8BITS |
|
||||
DMA_SCR_PBURST_SINGLE |
|
||||
DMA_SCR_MBURST_SINGLE);
|
||||
stm32_dmastart(_rx_dma, _dma_callback, this, false);
|
||||
rCR3 |= USART_CR3_DMAR;
|
||||
|
||||
/* start TX DMA - no callback if we also expect a reply */
|
||||
/* DMA setup time ~3µs */
|
||||
stm32_dmasetup(
|
||||
_tx_dma,
|
||||
PX4IO_SERIAL_BASE + STM32_USART_DR_OFFSET,
|
||||
reinterpret_cast<uint32_t>(_current_packet),
|
||||
PKT_SIZE(*_current_packet),
|
||||
DMA_SCR_DIR_M2P |
|
||||
DMA_SCR_MINC |
|
||||
DMA_SCR_PSIZE_8BITS |
|
||||
DMA_SCR_MSIZE_8BITS |
|
||||
DMA_SCR_PBURST_SINGLE |
|
||||
DMA_SCR_MBURST_SINGLE);
|
||||
stm32_dmastart(_tx_dma, nullptr, nullptr, false);
|
||||
//rCR1 &= ~USART_CR1_TE;
|
||||
//rCR1 |= USART_CR1_TE;
|
||||
rCR3 |= USART_CR3_DMAT;
|
||||
|
||||
perf_end(_pc_dmasetup);
|
||||
|
||||
/* compute the deadline for a 10ms timeout */
|
||||
struct timespec abstime;
|
||||
clock_gettime(CLOCK_REALTIME, &abstime);
|
||||
abstime.tv_nsec += 10 * 1000 * 1000;
|
||||
|
||||
if (abstime.tv_nsec >= 1000 * 1000 * 1000) {
|
||||
abstime.tv_sec++;
|
||||
abstime.tv_nsec -= 1000 * 1000 * 1000;
|
||||
}
|
||||
|
||||
/* wait for the transaction to complete - 64 bytes @ 1.5Mbps ~426µs */
|
||||
int ret;
|
||||
|
||||
for (;;) {
|
||||
ret = sem_timedwait(&_completion_semaphore, &abstime);
|
||||
|
||||
if (ret == OK) {
|
||||
/* check for DMA errors */
|
||||
if (_rx_dma_status & DMA_STATUS_TEIF) {
|
||||
perf_count(_pc_dmaerrs);
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
/* check packet CRC - corrupt packet errors mean IO receive CRC error */
|
||||
uint8_t crc = _current_packet->crc;
|
||||
_current_packet->crc = 0;
|
||||
|
||||
if ((crc != crc_packet(_current_packet)) || (PKT_CODE(*_current_packet) == PKT_CODE_CORRUPT)) {
|
||||
perf_count(_pc_crcerrs);
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
/* successful txn (may still be reporting an error) */
|
||||
break;
|
||||
}
|
||||
|
||||
if (errno == ETIMEDOUT) {
|
||||
/* something has broken - clear out any partial DMA state and reconfigure */
|
||||
_abort_dma();
|
||||
perf_count(_pc_timeouts);
|
||||
perf_cancel(_pc_txns); /* don't count this as a transaction */
|
||||
break;
|
||||
}
|
||||
|
||||
/* we might? see this for EINTR */
|
||||
syslog(LOG_ERR, "unexpected ret %d/%d\n", ret, errno);
|
||||
}
|
||||
|
||||
/* reset DMA status */
|
||||
_rx_dma_status = _dma_status_inactive;
|
||||
|
||||
/* update counters */
|
||||
perf_end(_pc_txns);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
PX4IO_serial_f4::_dma_callback(DMA_HANDLE handle, uint8_t status, void *arg)
|
||||
{
|
||||
if (arg != nullptr) {
|
||||
PX4IO_serial_f4 *ps = reinterpret_cast<PX4IO_serial_f4 *>(arg);
|
||||
|
||||
ps->_do_rx_dma_callback(status);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PX4IO_serial_f4::_do_rx_dma_callback(unsigned status)
|
||||
{
|
||||
/* on completion of a reply, wake the waiter */
|
||||
if (_rx_dma_status == _dma_status_waiting) {
|
||||
|
||||
/* check for packet overrun - this will occur after DMA completes */
|
||||
uint32_t sr = rSR;
|
||||
|
||||
if (sr & (USART_SR_ORE | USART_SR_RXNE)) {
|
||||
(void)rDR;
|
||||
status = DMA_STATUS_TEIF;
|
||||
}
|
||||
|
||||
/* save RX status */
|
||||
_rx_dma_status = status;
|
||||
|
||||
/* disable UART DMA */
|
||||
rCR3 &= ~(USART_CR3_DMAT | USART_CR3_DMAR);
|
||||
|
||||
/* complete now */
|
||||
px4_sem_post(&_completion_semaphore);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
PX4IO_serial_f4::_interrupt(int irq, void *context, void *arg)
|
||||
{
|
||||
if (arg != nullptr) {
|
||||
PX4IO_serial_f4 *instance = reinterpret_cast<PX4IO_serial_f4 *>(arg);
|
||||
|
||||
instance->_do_interrupt();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
PX4IO_serial_f4::_do_interrupt()
|
||||
{
|
||||
uint32_t sr = rSR; /* get UART status register */
|
||||
(void)rDR; /* read DR to clear status */
|
||||
|
||||
if (sr & (USART_SR_ORE | /* overrun error - packet was too big for DMA or DMA was too slow */
|
||||
USART_SR_NE | /* noise error - we have lost a byte due to noise */
|
||||
USART_SR_FE)) { /* framing error - start/stop bit lost or line break */
|
||||
|
||||
/*
|
||||
* If we are in the process of listening for something, these are all fatal;
|
||||
* abort the DMA with an error.
|
||||
*/
|
||||
if (_rx_dma_status == _dma_status_waiting) {
|
||||
_abort_dma();
|
||||
|
||||
perf_count(_pc_uerrs);
|
||||
/* complete DMA as though in error */
|
||||
_do_rx_dma_callback(DMA_STATUS_TEIF);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXX we might want to use FE / line break as an out-of-band handshake ... handle it here */
|
||||
|
||||
/* don't attempt to handle IDLE if it's set - things went bad */
|
||||
return;
|
||||
}
|
||||
|
||||
if (sr & USART_SR_IDLE) {
|
||||
|
||||
/* if there is DMA reception going on, this is a short packet */
|
||||
if (_rx_dma_status == _dma_status_waiting) {
|
||||
|
||||
/* verify that the received packet is complete */
|
||||
size_t length = sizeof(*_current_packet) - stm32_dmaresidual(_rx_dma);
|
||||
|
||||
if ((length < 1) || (length < PKT_SIZE(*_current_packet))) {
|
||||
perf_count(_pc_badidle);
|
||||
|
||||
/* stop the receive DMA */
|
||||
stm32_dmastop(_rx_dma);
|
||||
|
||||
/* complete the short reception */
|
||||
_do_rx_dma_callback(DMA_STATUS_TEIF);
|
||||
return;
|
||||
}
|
||||
|
||||
perf_count(_pc_idle);
|
||||
|
||||
/* stop the receive DMA */
|
||||
stm32_dmastop(_rx_dma);
|
||||
|
||||
/* complete the short reception */
|
||||
_do_rx_dma_callback(DMA_STATUS_TCIF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PX4IO_serial_f4::_abort_dma()
|
||||
{
|
||||
/* disable UART DMA */
|
||||
rCR3 &= ~(USART_CR3_DMAT | USART_CR3_DMAR);
|
||||
(void)rSR;
|
||||
(void)rDR;
|
||||
(void)rDR;
|
||||
|
||||
/* stop DMA */
|
||||
stm32_dmastop(_tx_dma);
|
||||
stm32_dmastop(_rx_dma);
|
||||
}
|
||||
|
||||
#endif /* PX4IO_INTERFACE_F4 */
|
||||
@@ -1,505 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2013-2015 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 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
|
||||
* 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 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file px4io_serial_f7.cpp
|
||||
*
|
||||
* Serial interface for PX4IO on STM32F7
|
||||
*/
|
||||
|
||||
#include "px4io_serial.h"
|
||||
|
||||
#ifdef PX4IO_INTERFACE_F7
|
||||
|
||||
#include "stm32_uart.h"
|
||||
#include <nuttx/cache.h>
|
||||
|
||||
/* serial register accessors */
|
||||
#define REG(_x) (*(volatile uint32_t *)(PX4IO_SERIAL_BASE + (_x)))
|
||||
#define rISR REG(STM32_USART_ISR_OFFSET)
|
||||
#define rISR_ERR_FLAGS_MASK (0x1f)
|
||||
#define rICR REG(STM32_USART_ICR_OFFSET)
|
||||
#define rRDR REG(STM32_USART_RDR_OFFSET)
|
||||
#define rTDR REG(STM32_USART_TDR_OFFSET)
|
||||
#define rBRR REG(STM32_USART_BRR_OFFSET)
|
||||
#define rCR1 REG(STM32_USART_CR1_OFFSET)
|
||||
#define rCR2 REG(STM32_USART_CR2_OFFSET)
|
||||
#define rCR3 REG(STM32_USART_CR3_OFFSET)
|
||||
#define rGTPR REG(STM32_USART_GTPR_OFFSET)
|
||||
|
||||
#define DMA_BUFFER_MASK (ARMV7M_DCACHE_LINESIZE - 1)
|
||||
#define DMA_ALIGN_UP(n) (((n) + DMA_BUFFER_MASK) & ~DMA_BUFFER_MASK)
|
||||
|
||||
uint8_t PX4IO_serial_f7::_io_buffer_storage[DMA_ALIGN_UP(sizeof(IOPacket))];
|
||||
|
||||
PX4IO_serial_f7::PX4IO_serial_f7() :
|
||||
_tx_dma(nullptr),
|
||||
_rx_dma(nullptr),
|
||||
_current_packet(nullptr),
|
||||
_rx_dma_status(_dma_status_inactive),
|
||||
_completion_semaphore(SEM_INITIALIZER(0)),
|
||||
#if 0
|
||||
_pc_dmasetup(perf_alloc(PC_ELAPSED, "io_dmasetup ")),
|
||||
_pc_dmaerrs(perf_alloc(PC_COUNT, "io_dmaerrs "))
|
||||
#else
|
||||
_pc_dmasetup(nullptr),
|
||||
_pc_dmaerrs(nullptr)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
PX4IO_serial_f7::~PX4IO_serial_f7()
|
||||
{
|
||||
if (_tx_dma != nullptr) {
|
||||
stm32_dmastop(_tx_dma);
|
||||
stm32_dmafree(_tx_dma);
|
||||
}
|
||||
|
||||
if (_rx_dma != nullptr) {
|
||||
stm32_dmastop(_rx_dma);
|
||||
stm32_dmafree(_rx_dma);
|
||||
}
|
||||
|
||||
/* reset the UART */
|
||||
rCR1 = 0;
|
||||
rCR2 = 0;
|
||||
rCR3 = 0;
|
||||
|
||||
/* detach our interrupt handler */
|
||||
up_disable_irq(PX4IO_SERIAL_VECTOR);
|
||||
irq_detach(PX4IO_SERIAL_VECTOR);
|
||||
|
||||
/* restore the GPIOs */
|
||||
px4_arch_unconfiggpio(PX4IO_SERIAL_TX_GPIO);
|
||||
px4_arch_unconfiggpio(PX4IO_SERIAL_RX_GPIO);
|
||||
|
||||
/* Disable APB clock for the USART peripheral */
|
||||
modifyreg32(PX4IO_SERIAL_RCC_REG, PX4IO_SERIAL_RCC_EN, 0);
|
||||
|
||||
/* and kill our semaphores */
|
||||
px4_sem_destroy(&_completion_semaphore);
|
||||
|
||||
perf_free(_pc_dmasetup);
|
||||
perf_free(_pc_dmaerrs);
|
||||
}
|
||||
|
||||
int
|
||||
PX4IO_serial_f7::init()
|
||||
{
|
||||
/* initialize base implementation */
|
||||
int r = PX4IO_serial::init((IOPacket *)&_io_buffer_storage[0]);
|
||||
|
||||
if (r != 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* allocate DMA */
|
||||
_tx_dma = stm32_dmachannel(PX4IO_SERIAL_TX_DMAMAP);
|
||||
_rx_dma = stm32_dmachannel(PX4IO_SERIAL_RX_DMAMAP);
|
||||
|
||||
if ((_tx_dma == nullptr) || (_rx_dma == nullptr)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Enable the APB clock for the USART peripheral */
|
||||
modifyreg32(PX4IO_SERIAL_RCC_REG, 0, PX4IO_SERIAL_RCC_EN);
|
||||
|
||||
/* configure pins for serial use */
|
||||
px4_arch_configgpio(PX4IO_SERIAL_TX_GPIO);
|
||||
px4_arch_configgpio(PX4IO_SERIAL_RX_GPIO);
|
||||
|
||||
/* reset & configure the UART */
|
||||
rCR1 = 0;
|
||||
rCR2 = 0;
|
||||
rCR3 = 0;
|
||||
|
||||
/* clear data that may be in the RDR and clear overrun error: */
|
||||
if (rISR & USART_ISR_RXNE) {
|
||||
(void)rRDR;
|
||||
}
|
||||
|
||||
rICR = rISR & rISR_ERR_FLAGS_MASK; /* clear the flags */
|
||||
|
||||
/* configure line speed */
|
||||
uint32_t usartdiv32 = (PX4IO_SERIAL_CLOCK + (PX4IO_SERIAL_BITRATE) / 2) / (PX4IO_SERIAL_BITRATE);
|
||||
rBRR = usartdiv32;
|
||||
|
||||
/* attach serial interrupt handler */
|
||||
irq_attach(PX4IO_SERIAL_VECTOR, _interrupt, this);
|
||||
up_enable_irq(PX4IO_SERIAL_VECTOR);
|
||||
|
||||
/* enable UART in DMA mode, enable error and line idle interrupts */
|
||||
rCR3 = USART_CR3_EIE;
|
||||
/* TODO: maybe use DDRE */
|
||||
|
||||
rCR1 = USART_CR1_RE | USART_CR1_TE | USART_CR1_UE | USART_CR1_IDLEIE;
|
||||
/* TODO: maybe we need to adhere to the procedure as described in the reference manual page 1251 (34.5.2) */
|
||||
|
||||
/* create semaphores */
|
||||
px4_sem_init(&_completion_semaphore, 0, 0);
|
||||
|
||||
/* _completion_semaphore use case is a signal */
|
||||
|
||||
px4_sem_setprotocol(&_completion_semaphore, SEM_PRIO_NONE);
|
||||
|
||||
/* XXX this could try talking to IO */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PX4IO_serial_f7::ioctl(unsigned operation, unsigned &arg)
|
||||
{
|
||||
switch (operation) {
|
||||
|
||||
case 1: /* XXX magic number - test operation */
|
||||
switch (arg) {
|
||||
case 0:
|
||||
syslog(LOG_INFO, "test 0\n");
|
||||
|
||||
/* kill DMA, this is a PIO test */
|
||||
stm32_dmastop(_tx_dma);
|
||||
stm32_dmastop(_rx_dma);
|
||||
rCR3 &= ~(USART_CR3_DMAR | USART_CR3_DMAT);
|
||||
|
||||
for (;;) {
|
||||
while (!(rISR & USART_ISR_TXE))
|
||||
;
|
||||
|
||||
rTDR = 0x55;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case 1: {
|
||||
unsigned fails = 0;
|
||||
|
||||
for (unsigned count = 0;; count++) {
|
||||
uint16_t value = count & 0xffff;
|
||||
|
||||
if (write((PX4IO_PAGE_TEST << 8) | PX4IO_P_TEST_LED, &value, 1) != 0) {
|
||||
fails++;
|
||||
}
|
||||
|
||||
if (count >= 5000) {
|
||||
syslog(LOG_INFO, "==== test 1 : %u failures ====\n", fails);
|
||||
perf_print_counter(_pc_txns);
|
||||
perf_print_counter(_pc_dmasetup);
|
||||
perf_print_counter(_pc_retries);
|
||||
perf_print_counter(_pc_timeouts);
|
||||
perf_print_counter(_pc_crcerrs);
|
||||
perf_print_counter(_pc_dmaerrs);
|
||||
perf_print_counter(_pc_protoerrs);
|
||||
perf_print_counter(_pc_uerrs);
|
||||
perf_print_counter(_pc_idle);
|
||||
perf_print_counter(_pc_badidle);
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case 2:
|
||||
syslog(LOG_INFO, "test 2\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
PX4IO_serial_f7::_bus_exchange(IOPacket *_packet)
|
||||
{
|
||||
_current_packet = _packet;
|
||||
|
||||
/* clear data that may be in the RDR and clear overrun error: */
|
||||
if (rISR & USART_ISR_RXNE) {
|
||||
(void)rRDR;
|
||||
}
|
||||
|
||||
rICR = rISR & rISR_ERR_FLAGS_MASK; /* clear the flags */
|
||||
|
||||
/* start RX DMA */
|
||||
perf_begin(_pc_txns);
|
||||
perf_begin(_pc_dmasetup);
|
||||
|
||||
/* DMA setup time ~3µs */
|
||||
_rx_dma_status = _dma_status_waiting;
|
||||
|
||||
/*
|
||||
* Note that we enable circular buffer mode as a workaround for
|
||||
* there being no API to disable the DMA FIFO. We need direct mode
|
||||
* because otherwise when the line idle interrupt fires there
|
||||
* will be packet bytes still in the DMA FIFO, and we will assume
|
||||
* that the idle was spurious.
|
||||
*
|
||||
* XXX this should be fixed with a NuttX change.
|
||||
*/
|
||||
stm32_dmasetup(
|
||||
_rx_dma,
|
||||
PX4IO_SERIAL_BASE + STM32_USART_RDR_OFFSET,
|
||||
reinterpret_cast<uint32_t>(_current_packet),
|
||||
sizeof(*_current_packet),
|
||||
DMA_SCR_CIRC | /* XXX see note above */
|
||||
DMA_SCR_DIR_P2M |
|
||||
DMA_SCR_MINC |
|
||||
DMA_SCR_PSIZE_8BITS |
|
||||
DMA_SCR_MSIZE_8BITS |
|
||||
DMA_SCR_PBURST_SINGLE |
|
||||
DMA_SCR_MBURST_SINGLE);
|
||||
rCR3 |= USART_CR3_DMAR;
|
||||
stm32_dmastart(_rx_dma, _dma_callback, this, false);
|
||||
|
||||
/* Clean _current_packet, so DMA can see the data */
|
||||
up_clean_dcache((uintptr_t)_current_packet,
|
||||
(uintptr_t)_current_packet + DMA_ALIGN_UP(sizeof(IOPacket)));
|
||||
|
||||
/* start TX DMA - no callback if we also expect a reply */
|
||||
/* DMA setup time ~3µs */
|
||||
stm32_dmasetup(
|
||||
_tx_dma,
|
||||
PX4IO_SERIAL_BASE + STM32_USART_TDR_OFFSET,
|
||||
reinterpret_cast<uint32_t>(_current_packet),
|
||||
PKT_SIZE(*_current_packet),
|
||||
DMA_SCR_DIR_M2P |
|
||||
DMA_SCR_MINC |
|
||||
DMA_SCR_PSIZE_8BITS |
|
||||
DMA_SCR_MSIZE_8BITS |
|
||||
DMA_SCR_PBURST_SINGLE |
|
||||
DMA_SCR_MBURST_SINGLE);
|
||||
rCR3 |= USART_CR3_DMAT;
|
||||
stm32_dmastart(_tx_dma, nullptr, nullptr, false);
|
||||
//rCR1 &= ~USART_CR1_TE;
|
||||
//rCR1 |= USART_CR1_TE;
|
||||
|
||||
perf_end(_pc_dmasetup);
|
||||
|
||||
/* compute the deadline for a 10ms timeout */
|
||||
struct timespec abstime;
|
||||
clock_gettime(CLOCK_REALTIME, &abstime);
|
||||
abstime.tv_nsec += 10 * 1000 * 1000;
|
||||
|
||||
if (abstime.tv_nsec >= 1000 * 1000 * 1000) {
|
||||
abstime.tv_sec++;
|
||||
abstime.tv_nsec -= 1000 * 1000 * 1000;
|
||||
}
|
||||
|
||||
/* wait for the transaction to complete - 64 bytes @ 1.5Mbps ~426µs */
|
||||
int ret;
|
||||
|
||||
for (;;) {
|
||||
ret = sem_timedwait(&_completion_semaphore, &abstime);
|
||||
|
||||
if (ret == OK) {
|
||||
/* check for DMA errors */
|
||||
if (_rx_dma_status & DMA_STATUS_TEIF) {
|
||||
perf_count(_pc_dmaerrs);
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
/* check packet CRC - corrupt packet errors mean IO receive CRC error */
|
||||
uint8_t crc = _current_packet->crc;
|
||||
_current_packet->crc = 0;
|
||||
|
||||
if ((crc != crc_packet(_current_packet)) || (PKT_CODE(*_current_packet) == PKT_CODE_CORRUPT)) {
|
||||
perf_count(_pc_crcerrs);
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
/* successful txn (may still be reporting an error) */
|
||||
break;
|
||||
}
|
||||
|
||||
if (errno == ETIMEDOUT) {
|
||||
/* something has broken - clear out any partial DMA state and reconfigure */
|
||||
_abort_dma();
|
||||
perf_count(_pc_timeouts);
|
||||
perf_cancel(_pc_txns); /* don't count this as a transaction */
|
||||
break;
|
||||
}
|
||||
|
||||
/* we might? see this for EINTR */
|
||||
syslog(LOG_ERR, "unexpected ret %d/%d\n", ret, errno);
|
||||
}
|
||||
|
||||
/* reset DMA status */
|
||||
_rx_dma_status = _dma_status_inactive;
|
||||
|
||||
/* update counters */
|
||||
perf_end(_pc_txns);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
PX4IO_serial_f7::_dma_callback(DMA_HANDLE handle, uint8_t status, void *arg)
|
||||
{
|
||||
if (arg != nullptr) {
|
||||
PX4IO_serial_f7 *ps = reinterpret_cast<PX4IO_serial_f7 *>(arg);
|
||||
|
||||
ps->_do_rx_dma_callback(status);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PX4IO_serial_f7::_do_rx_dma_callback(unsigned status)
|
||||
{
|
||||
/* on completion of a reply, wake the waiter */
|
||||
if (_rx_dma_status == _dma_status_waiting) {
|
||||
|
||||
/* check for packet overrun - this will occur after DMA completes */
|
||||
uint32_t sr = rISR;
|
||||
|
||||
if (sr & (USART_ISR_ORE | USART_ISR_RXNE)) {
|
||||
(void)rRDR;
|
||||
rICR = sr & (USART_ISR_ORE | USART_ISR_RXNE);
|
||||
status = DMA_STATUS_TEIF;
|
||||
}
|
||||
|
||||
/* save RX status */
|
||||
_rx_dma_status = status;
|
||||
|
||||
/* disable UART DMA */
|
||||
rCR3 &= ~(USART_CR3_DMAT | USART_CR3_DMAR);
|
||||
|
||||
/* complete now */
|
||||
px4_sem_post(&_completion_semaphore);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
PX4IO_serial_f7::_interrupt(int irq, void *context, void *arg)
|
||||
{
|
||||
if (arg != nullptr) {
|
||||
PX4IO_serial_f7 *instance = reinterpret_cast<PX4IO_serial_f7 *>(arg);
|
||||
|
||||
instance->_do_interrupt();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
PX4IO_serial_f7::_do_interrupt()
|
||||
{
|
||||
uint32_t sr = rISR; /* get UART status register */
|
||||
|
||||
if (sr & USART_ISR_RXNE) {
|
||||
(void)rRDR; /* read DR to clear RXNE */
|
||||
}
|
||||
|
||||
rICR = sr & rISR_ERR_FLAGS_MASK; /* clear flags */
|
||||
|
||||
if (sr & (USART_ISR_ORE | /* overrun error - packet was too big for DMA or DMA was too slow */
|
||||
USART_ISR_NF | /* noise error - we have lost a byte due to noise */
|
||||
USART_ISR_FE)) { /* framing error - start/stop bit lost or line break */
|
||||
|
||||
/*
|
||||
* If we are in the process of listening for something, these are all fatal;
|
||||
* abort the DMA with an error.
|
||||
*/
|
||||
if (_rx_dma_status == _dma_status_waiting) {
|
||||
_abort_dma();
|
||||
|
||||
perf_count(_pc_uerrs);
|
||||
/* complete DMA as though in error */
|
||||
_do_rx_dma_callback(DMA_STATUS_TEIF);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXX we might want to use FE / line break as an out-of-band handshake ... handle it here */
|
||||
|
||||
/* don't attempt to handle IDLE if it's set - things went bad */
|
||||
return;
|
||||
}
|
||||
|
||||
if (sr & USART_ISR_IDLE) {
|
||||
|
||||
/* if there is DMA reception going on, this is a short packet */
|
||||
if (_rx_dma_status == _dma_status_waiting) {
|
||||
/* Invalidate _current_packet, so we get fresh data from RAM */
|
||||
up_invalidate_dcache((uintptr_t)_current_packet,
|
||||
(uintptr_t)_current_packet + DMA_ALIGN_UP(sizeof(IOPacket)));
|
||||
|
||||
/* verify that the received packet is complete */
|
||||
size_t length = sizeof(*_current_packet) - stm32_dmaresidual(_rx_dma);
|
||||
|
||||
if ((length < 1) || (length < PKT_SIZE(*_current_packet))) {
|
||||
perf_count(_pc_badidle);
|
||||
|
||||
/* stop the receive DMA */
|
||||
stm32_dmastop(_rx_dma);
|
||||
|
||||
/* complete the short reception */
|
||||
_do_rx_dma_callback(DMA_STATUS_TEIF);
|
||||
return;
|
||||
}
|
||||
|
||||
perf_count(_pc_idle);
|
||||
|
||||
/* stop the receive DMA */
|
||||
stm32_dmastop(_rx_dma);
|
||||
|
||||
/* complete the short reception */
|
||||
_do_rx_dma_callback(DMA_STATUS_TCIF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PX4IO_serial_f7::_abort_dma()
|
||||
{
|
||||
/* stop DMA */
|
||||
stm32_dmastop(_tx_dma);
|
||||
stm32_dmastop(_rx_dma);
|
||||
|
||||
/* disable UART DMA */
|
||||
rCR3 &= ~(USART_CR3_DMAT | USART_CR3_DMAR);
|
||||
|
||||
/* clear data that may be in the RDR and clear overrun error: */
|
||||
if (rISR & USART_ISR_RXNE) {
|
||||
(void)rRDR;
|
||||
}
|
||||
|
||||
rICR = rISR & rISR_ERR_FLAGS_MASK; /* clear the flags */
|
||||
}
|
||||
|
||||
#endif /* PX4IO_INTERFACE_F7 */
|
||||
@@ -1,36 +0,0 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2015-2019 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. 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
|
||||
# distribution.
|
||||
# 3. Neither the name PX4 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
|
||||
# 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 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
px4_add_library(tone_alarm_interface
|
||||
ToneAlarmInterface.cpp
|
||||
)
|
||||
@@ -1,54 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2013-2019 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 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
|
||||
* 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 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file ToneAlarmInterface.cpp
|
||||
*/
|
||||
|
||||
#include <lib/drivers/tone_alarm/ToneAlarmInterface.h>
|
||||
#include <px4_defines.h>
|
||||
|
||||
void ToneAlarmInterface::init()
|
||||
{
|
||||
// Nothing to be done in simulation.
|
||||
}
|
||||
|
||||
void ToneAlarmInterface::start_note(unsigned frequency)
|
||||
{
|
||||
// Nothing to be done in simulation.
|
||||
}
|
||||
|
||||
void ToneAlarmInterface::stop_note()
|
||||
{
|
||||
// Nothing to be done in simulation.
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2015-2019 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. 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
|
||||
# distribution.
|
||||
# 3. Neither the name PX4 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
|
||||
# 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 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
px4_add_library(tone_alarm_interface
|
||||
ToneAlarmInterface.cpp
|
||||
)
|
||||
@@ -1,40 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2019 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 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
|
||||
* 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 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <board_config.h>
|
||||
|
||||
#ifdef GPIO_TONE_ALARM_GPIO
|
||||
#include "ToneAlarmInterfaceGPIO.cpp"
|
||||
#else
|
||||
#include "ToneAlarmInterfacePWM.cpp"
|
||||
#endif
|
||||
@@ -1,53 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2019 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 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
|
||||
* 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 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <lib/drivers/tone_alarm/ToneAlarmInterface.h>
|
||||
#include <px4_defines.h>
|
||||
#include <board_config.h>
|
||||
|
||||
void ToneAlarmInterface::init()
|
||||
{
|
||||
// Configure the GPIO to the idle state.
|
||||
px4_arch_configgpio(GPIO_TONE_ALARM_IDLE);
|
||||
}
|
||||
|
||||
void ToneAlarmInterface::start_note(unsigned frequency)
|
||||
{
|
||||
px4_arch_gpiowrite(GPIO_TONE_ALARM_GPIO, 1);
|
||||
}
|
||||
|
||||
void ToneAlarmInterface::stop_note()
|
||||
{
|
||||
// Stop the current note.
|
||||
px4_arch_gpiowrite(GPIO_TONE_ALARM_GPIO, 0);
|
||||
}
|
||||
@@ -1,286 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2013-2019 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 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
|
||||
* 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 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <drivers/device/device.h>
|
||||
#include <lib/drivers/tone_alarm/ToneAlarmInterface.h>
|
||||
#include <px4_defines.h>
|
||||
#include <cmath>
|
||||
|
||||
/* Check that tone alarm and HRT timers are different */
|
||||
#if defined(TONE_ALARM_TIMER) && defined(HRT_TIMER)
|
||||
# if TONE_ALARM_TIMER == HRT_TIMER
|
||||
# error TONE_ALARM_TIMER and HRT_TIMER must use different timers.
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Period of the free-running counter, in microseconds. */
|
||||
#ifndef TONE_ALARM_COUNTER_PERIOD
|
||||
#define TONE_ALARM_COUNTER_PERIOD 65536
|
||||
#endif
|
||||
|
||||
/* Tone alarm configuration */
|
||||
#if TONE_ALARM_TIMER == 1
|
||||
# define TONE_ALARM_BASE STM32_TIM1_BASE
|
||||
# define TONE_ALARM_CLOCK STM32_APB2_TIM1_CLKIN
|
||||
# define TONE_ALARM_CLOCK_ENABLE RCC_APB2ENR_TIM1EN
|
||||
# define TONE_ALARM_CLOCK_POWER_REG STM32_RCC_APB2ENR
|
||||
# if defined(CONFIG_STM32_TIM1)
|
||||
# error Must not set CONFIG_STM32_TIM1 when TONE_ALARM_TIMER is 1
|
||||
# endif
|
||||
#elif TONE_ALARM_TIMER == 2
|
||||
# define TONE_ALARM_BASE STM32_TIM2_BASE
|
||||
# define TONE_ALARM_CLOCK STM32_APB1_TIM2_CLKIN
|
||||
# define TONE_ALARM_CLOCK_ENABLE RCC_APB1ENR_TIM2EN
|
||||
# define TONE_ALARM_CLOCK_POWER_REG STM32_RCC_APB1ENR
|
||||
# if defined(CONFIG_STM32_TIM2)
|
||||
# error Must not set CONFIG_STM32_TIM2 when TONE_ALARM_TIMER is 2
|
||||
# endif
|
||||
#elif TONE_ALARM_TIMER == 3
|
||||
# define TONE_ALARM_BASE STM32_TIM3_BASE
|
||||
# define TONE_ALARM_CLOCK STM32_APB1_TIM3_CLKIN
|
||||
# define TONE_ALARM_CLOCK_ENABLE RCC_APB1ENR_TIM3EN
|
||||
# define TONE_ALARM_CLOCK_POWER_REG STM32_RCC_APB1ENR
|
||||
# if defined(CONFIG_STM32_TIM3)
|
||||
# error Must not set CONFIG_STM32_TIM3 when TONE_ALARM_TIMER is 3
|
||||
# endif
|
||||
#elif TONE_ALARM_TIMER == 4
|
||||
# define TONE_ALARM_BASE STM32_TIM4_BASE
|
||||
# define TONE_ALARM_CLOCK STM32_APB1_TIM4_CLKIN
|
||||
# define TONE_ALARM_CLOCK_ENABLE RCC_APB1ENR_TIM4EN
|
||||
# define TONE_ALARM_CLOCK_POWER_REG STM32_RCC_APB1ENR
|
||||
# if defined(CONFIG_STM32_TIM4)
|
||||
# error Must not set CONFIG_STM32_TIM4 when TONE_ALARM_TIMER is 4
|
||||
# endif
|
||||
#elif TONE_ALARM_TIMER == 5
|
||||
# define TONE_ALARM_BASE STM32_TIM5_BASE
|
||||
# define TONE_ALARM_CLOCK STM32_APB1_TIM5_CLKIN
|
||||
# define TONE_ALARM_CLOCK_ENABLE RCC_APB1ENR_TIM5EN
|
||||
# define TONE_ALARM_CLOCK_POWER_REG STM32_RCC_APB1ENR
|
||||
# if defined(CONFIG_STM32_TIM5)
|
||||
# error Must not set CONFIG_STM32_TIM5 when TONE_ALARM_TIMER is 5
|
||||
# endif
|
||||
#elif TONE_ALARM_TIMER == 8
|
||||
# define TONE_ALARM_BASE STM32_TIM8_BASE
|
||||
# define TONE_ALARM_CLOCK STM32_APB2_TIM8_CLKIN
|
||||
# define TONE_ALARM_CLOCK_ENABLE RCC_APB2ENR_TIM8EN
|
||||
# define TONE_ALARM_CLOCK_POWER_REG STM32_RCC_APB2ENR
|
||||
# if defined(CONFIG_STM32_TIM8)
|
||||
# error Must not set CONFIG_STM32_TIM8 when TONE_ALARM_TIMER is 8
|
||||
# endif
|
||||
#elif TONE_ALARM_TIMER == 9
|
||||
# define TONE_ALARM_BASE STM32_TIM9_BASE
|
||||
# define TONE_ALARM_CLOCK STM32_APB2_TIM9_CLKIN
|
||||
# define TONE_ALARM_CLOCK_ENABLE RCC_APB2ENR_TIM9EN
|
||||
# define TONE_ALARM_CLOCK_POWER_REG STM32_RCC_APB2ENR
|
||||
# if defined(CONFIG_STM32_TIM9)
|
||||
# error Must not set CONFIG_STM32_TIM9 when TONE_ALARM_TIMER is 9
|
||||
# endif
|
||||
#elif TONE_ALARM_TIMER == 10
|
||||
# define TONE_ALARM_BASE STM32_TIM10_BASE
|
||||
# define TONE_ALARM_CLOCK STM32_APB2_TIM10_CLKIN
|
||||
# define TONE_ALARM_CLOCK_ENABLE RCC_APB2ENR_TIM10EN
|
||||
# define TONE_ALARM_CLOCK_POWER_REG STM32_RCC_APB2ENR
|
||||
# if defined(CONFIG_STM32_TIM10)
|
||||
# error Must not set CONFIG_STM32_TIM10 when TONE_ALARM_TIMER is 10
|
||||
# endif
|
||||
#elif TONE_ALARM_TIMER == 11
|
||||
# define TONE_ALARM_BASE STM32_TIM11_BASE
|
||||
# define TONE_ALARM_CLOCK STM32_APB2_TIM11_CLKIN
|
||||
# define TONE_ALARM_CLOCK_ENABLE RCC_APB2ENR_TIM11EN
|
||||
# define TONE_ALARM_CLOCK_POWER_REG STM32_RCC_APB2ENR
|
||||
# if defined(CONFIG_STM32_TIM11)
|
||||
# error Must not set CONFIG_STM32_TIM11 when TONE_ALARM_TIMER is 11
|
||||
# endif
|
||||
#elif TONE_ALARM_TIMER == 12
|
||||
# define TONE_ALARM_BASE STM32_TIM12_BASE
|
||||
# define TONE_ALARM_CLOCK STM32_APB1_TIM12_CLKIN
|
||||
# define TONE_ALARM_CLOCK_ENABLE RCC_APB1ENR_TIM12EN
|
||||
# define TONE_ALARM_CLOCK_POWER_REG STM32_RCC_APB1ENR
|
||||
# if defined(CONFIG_STM32_TIM12)
|
||||
# error Must not set CONFIG_STM32_TIM12 when TONE_ALARM_TIMER is 12
|
||||
# endif
|
||||
#elif TONE_ALARM_TIMER == 13
|
||||
# define TONE_ALARM_BASE STM32_TIM13_BASE
|
||||
# define TONE_ALARM_CLOCK STM32_APB1_TIM13_CLKIN
|
||||
# define TONE_ALARM_CLOCK_ENABLE RCC_APB1ENR_TIM13EN
|
||||
# define TONE_ALARM_CLOCK_POWER_REG STM32_RCC_APB1ENR
|
||||
# if defined(CONFIG_STM32_TIM13)
|
||||
# error Must not set CONFIG_STM32_TIM13 when TONE_ALARM_TIMER is 13
|
||||
# endif
|
||||
#elif TONE_ALARM_TIMER == 14
|
||||
# define TONE_ALARM_BASE STM32_TIM14_BASE
|
||||
# define TONE_ALARM_CLOCK STM32_APB1_TIM14_CLKIN
|
||||
# define TONE_ALARM_CLOCK_ENABLE RCC_APB1ENR_TIM14EN
|
||||
# define TONE_ALARM_CLOCK_POWER_REG STM32_RCC_APB1ENR
|
||||
# if defined(CONFIG_STM32_TIM14)
|
||||
# error Must not set CONFIG_STM32_TIM14 when TONE_ALARM_TIMER is 14
|
||||
# endif
|
||||
#else
|
||||
# error Must set TONE_ALARM_TIMER to one of the timers between 1 and 14 (inclusive) to use this driver.
|
||||
#endif // TONE_ALARM_TIMER
|
||||
|
||||
#if TONE_ALARM_CHANNEL == 1
|
||||
# define TONE_CCER (1 << 0)
|
||||
# define TONE_CCMR1 (3 << 4)
|
||||
# define TONE_CCMR2 0
|
||||
# define TONE_rCCR rCCR1
|
||||
#elif TONE_ALARM_CHANNEL == 2
|
||||
# define TONE_CCER (1 << 4)
|
||||
# define TONE_CCMR1 (3 << 12)
|
||||
# define TONE_CCMR2 0
|
||||
# define TONE_rCCR rCCR2
|
||||
#elif TONE_ALARM_CHANNEL == 3
|
||||
# define TONE_CCER (1 << 8)
|
||||
# define TONE_CCMR1 0
|
||||
# define TONE_CCMR2 (3 << 4)
|
||||
# define TONE_rCCR rCCR3
|
||||
#elif TONE_ALARM_CHANNEL == 4
|
||||
# define TONE_CCER (1 << 12)
|
||||
# define TONE_CCMR1 0
|
||||
# define TONE_CCMR2 (3 << 12)
|
||||
# define TONE_rCCR rCCR4
|
||||
#else
|
||||
# error Must set TONE_ALARM_CHANNEL to a value between 1 and 4 to use this driver.
|
||||
#endif // TONE_ALARM_CHANNEL
|
||||
|
||||
/* Timer register accessors. */
|
||||
#define REG(_reg) (*(volatile uint32_t *)(TONE_ALARM_BASE + _reg))
|
||||
|
||||
#if TONE_ALARM_TIMER == 1 || TONE_ALARM_TIMER == 8 // Note: If using TIM1 or TIM8, then you are using the ADVANCED timers and NOT the GENERAL TIMERS, therefore different registers
|
||||
# define rARR REG(STM32_ATIM_ARR_OFFSET)
|
||||
# define rBDTR REG(STM32_ATIM_BDTR_OFFSET)
|
||||
# define rCCER REG(STM32_ATIM_CCER_OFFSET)
|
||||
# define rCCMR1 REG(STM32_ATIM_CCMR1_OFFSET)
|
||||
# define rCCMR2 REG(STM32_ATIM_CCMR2_OFFSET)
|
||||
# define rCCR1 REG(STM32_ATIM_CCR1_OFFSET)
|
||||
# define rCCR2 REG(STM32_ATIM_CCR2_OFFSET)
|
||||
# define rCCR3 REG(STM32_ATIM_CCR3_OFFSET)
|
||||
# define rCCR4 REG(STM32_ATIM_CCR4_OFFSET)
|
||||
# define rCNT REG(STM32_ATIM_CNT_OFFSET)
|
||||
# define rCR1 REG(STM32_ATIM_CR1_OFFSET)
|
||||
# define rCR2 REG(STM32_ATIM_CR2_OFFSET)
|
||||
# define rDCR REG(STM32_ATIM_DCR_OFFSET)
|
||||
# define rDIER REG(STM32_ATIM_DIER_OFFSET)
|
||||
# define rDMAR REG(STM32_ATIM_DMAR_OFFSET)
|
||||
# define rEGR REG(STM32_ATIM_EGR_OFFSET)
|
||||
# define rPSC REG(STM32_ATIM_PSC_OFFSET)
|
||||
# define rRCR REG(STM32_ATIM_RCR_OFFSET)
|
||||
# define rSMCR REG(STM32_ATIM_SMCR_OFFSET)
|
||||
# define rSR REG(STM32_ATIM_SR_OFFSET)
|
||||
#else
|
||||
# define rARR REG(STM32_GTIM_ARR_OFFSET)
|
||||
# define rCCER REG(STM32_GTIM_CCER_OFFSET)
|
||||
# define rCCMR1 REG(STM32_GTIM_CCMR1_OFFSET)
|
||||
# define rCCMR2 REG(STM32_GTIM_CCMR2_OFFSET)
|
||||
# define rCCR1 REG(STM32_GTIM_CCR1_OFFSET)
|
||||
# define rCCR2 REG(STM32_GTIM_CCR2_OFFSET)
|
||||
# define rCCR3 REG(STM32_GTIM_CCR3_OFFSET)
|
||||
# define rCCR4 REG(STM32_GTIM_CCR4_OFFSET)
|
||||
# define rCNT REG(STM32_GTIM_CNT_OFFSET)
|
||||
# define rCR1 REG(STM32_GTIM_CR1_OFFSET)
|
||||
# define rCR2 REG(STM32_GTIM_CR2_OFFSET)
|
||||
# define rDCR REG(STM32_GTIM_DCR_OFFSET)
|
||||
# define rDIER REG(STM32_GTIM_DIER_OFFSET)
|
||||
# define rDMAR REG(STM32_GTIM_DMAR_OFFSET)
|
||||
# define rEGR REG(STM32_GTIM_EGR_OFFSET)
|
||||
# define rPSC REG(STM32_GTIM_PSC_OFFSET)
|
||||
# define rRCR REG(STM32_GTIM_RCR_OFFSET)
|
||||
# define rSMCR REG(STM32_GTIM_SMCR_OFFSET)
|
||||
# define rSR REG(STM32_GTIM_SR_OFFSET)
|
||||
#endif
|
||||
|
||||
void ToneAlarmInterface::init()
|
||||
{
|
||||
#ifdef GPIO_TONE_ALARM_NEG
|
||||
px4_arch_configgpio(GPIO_TONE_ALARM_NEG);
|
||||
#else
|
||||
// Configure the GPIO to the idle state.
|
||||
px4_arch_configgpio(GPIO_TONE_ALARM_IDLE);
|
||||
#endif
|
||||
|
||||
// Clock/power on our timer.
|
||||
modifyreg32(TONE_ALARM_CLOCK_POWER_REG, 0, TONE_ALARM_CLOCK_ENABLE);
|
||||
|
||||
// Initialize the timer.
|
||||
rCCER &= TONE_CCER; // Unlock CCMR* registers.
|
||||
rCCER = TONE_CCER;
|
||||
rCCMR1 = TONE_CCMR1;
|
||||
rCCMR2 = TONE_CCMR2;
|
||||
rCR1 = 0;
|
||||
rCR2 = 0;
|
||||
rDCR = 0;
|
||||
rDIER = 0;
|
||||
rSMCR = 0;
|
||||
|
||||
#ifdef rBDTR // If using an advanced timer, you need to activate the output.
|
||||
rBDTR = ATIM_BDTR_MOE; // Enable the main output of the advanced timer.
|
||||
#endif
|
||||
|
||||
TONE_rCCR = 1; // Toggle the CC output each time the count passes 1.
|
||||
rPSC = 0; // Default the timer to a prescale value of 1; playing notes will change this.
|
||||
rCR1 = GTIM_CR1_CEN; // Ensure the timer is running.
|
||||
}
|
||||
|
||||
void ToneAlarmInterface::start_note(unsigned frequency)
|
||||
{
|
||||
// Calculate the signal switching period.
|
||||
// (Signal switching period is one half of the frequency period).
|
||||
float signal_period = (1.0f / frequency) * 0.5f;
|
||||
|
||||
// Calculate the hardware clock divisor rounded to the nearest integer.
|
||||
unsigned int divisor = std::round(signal_period * TONE_ALARM_CLOCK);
|
||||
|
||||
// Pick the lowest prescaler value that we can use.
|
||||
// (Note that the effective prescale value is 1 greater.)
|
||||
unsigned int prescale = divisor / TONE_ALARM_COUNTER_PERIOD;
|
||||
|
||||
// Calculate the period for the selected prescaler value.
|
||||
unsigned int period = (divisor / (prescale + 1)) - 1;
|
||||
|
||||
rPSC = prescale; // Load new prescaler.
|
||||
rARR = period; // Load new toggle period.
|
||||
rEGR = GTIM_EGR_UG; // Force a reload of the period.
|
||||
rCCER |= TONE_CCER; // Enable the output.
|
||||
|
||||
// Configure the GPIO to enable timer output.
|
||||
px4_arch_configgpio(GPIO_TONE_ALARM);
|
||||
}
|
||||
|
||||
void ToneAlarmInterface::stop_note()
|
||||
{
|
||||
// Stop the current note.
|
||||
rCCER &= ~TONE_CCER;
|
||||
|
||||
// Ensure the GPIO is not driving the speaker.
|
||||
px4_arch_configgpio(GPIO_TONE_ALARM_IDLE);
|
||||
}
|
||||
@@ -38,6 +38,6 @@ px4_add_module(
|
||||
ToneAlarm.cpp
|
||||
DEPENDS
|
||||
circuit_breaker
|
||||
tone_alarm_interface
|
||||
arch_tone_alarm
|
||||
tunes
|
||||
)
|
||||
|
||||
@@ -45,6 +45,7 @@ add_library(px4iofirmware
|
||||
set_property(GLOBAL APPEND PROPERTY PX4_MODULE_LIBRARIES px4iofirmware)
|
||||
target_link_libraries(px4iofirmware
|
||||
PUBLIC
|
||||
arch_io_pins
|
||||
nuttx_apps
|
||||
nuttx_arch
|
||||
nuttx_c
|
||||
@@ -52,4 +53,4 @@ target_link_libraries(px4iofirmware
|
||||
rc
|
||||
perf
|
||||
pwm_limit
|
||||
)
|
||||
)
|
||||
|
||||
@@ -31,199 +31,11 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is a shim to bridge to the many SoC architecture supported by PX4
|
||||
*/
|
||||
|
||||
#ifdef __PX4_NUTTX
|
||||
__BEGIN_DECLS
|
||||
#include <nuttx/spi/spi.h>
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
// include arch-specific header
|
||||
#include <px4_arch_micro_hal.h>
|
||||
|
||||
/* For historical reasons (NuttX STM32 numbering) PX4 bus numbering is 1 based
|
||||
* All PX4 code, including, board code is written to assuming 1 based numbering.
|
||||
* The following macros are used to allow the board config to define the bus
|
||||
* numbers in terms of the NuttX driver numbering. 1,2,3 for one based numbering
|
||||
* schemes or 0,1,2 for zero based schemes.
|
||||
*/
|
||||
|
||||
#define PX4_BUS_NUMBER_TO_PX4(x) ((x)+PX4_BUS_OFFSET) /* Use to define Zero based to match Nuttx Driver but provide 1 based to PX4 */
|
||||
#define PX4_BUS_NUMBER_FROM_PX4(x) ((x)-PX4_BUS_OFFSET) /* Use to map PX4 1 based to NuttX driver 0 based */
|
||||
|
||||
# define px4_enter_critical_section() enter_critical_section()
|
||||
# define px4_leave_critical_section(flags) leave_critical_section(flags)
|
||||
|
||||
# if defined(CONFIG_ARCH_CHIP_STM32) || defined(CONFIG_ARCH_CHIP_STM32F7)
|
||||
|
||||
# if defined(CONFIG_ARCH_CHIP_STM32)
|
||||
# include <stm32.h>
|
||||
# define PX4_SOC_ARCH_ID PX4_SOC_ARCH_ID_STM32F4
|
||||
# define PX4_FLASH_BASE STM32_FLASH_BASE
|
||||
# if defined(CONFIG_STM32_STM32F4XXX)
|
||||
# include <stm32_bbsram.h>
|
||||
# define PX4_BBSRAM_SIZE STM32_BBSRAM_SIZE
|
||||
# define PX4_BBSRAM_GETDESC_IOCTL STM32_BBSRAM_GETDESC_IOCTL
|
||||
# endif
|
||||
# define PX4_NUMBER_I2C_BUSES STM32_NI2C
|
||||
# endif
|
||||
|
||||
# if defined(CONFIG_ARCH_CHIP_STM32F7)
|
||||
# define PX4_SOC_ARCH_ID PX4_SOC_ARCH_ID_STM32F7
|
||||
# include <chip.h>
|
||||
# include <chip/stm32_flash.h>
|
||||
void stm32_flash_lock(void);
|
||||
void stm32_flash_unlock(void);
|
||||
int stm32_flash_writeprotect(size_t page, bool enabled);
|
||||
# include <up_internal.h> //include up_systemreset() which is included on stm32.h
|
||||
# include <stm32_bbsram.h>
|
||||
# define PX4_BBSRAM_SIZE STM32F7_BBSRAM_SIZE
|
||||
# define PX4_BBSRAM_GETDESC_IOCTL STM32F7_BBSRAM_GETDESC_IOCTL
|
||||
# define PX4_FLASH_BASE 0x08000000
|
||||
# define PX4_NUMBER_I2C_BUSES STM32F7_NI2C
|
||||
# endif
|
||||
|
||||
# include <stm32_tim.h>
|
||||
# include <stm32_spi.h>
|
||||
# include <stm32_i2c.h>
|
||||
|
||||
/* STM32/32F7 defines the 96 bit UUID as
|
||||
* init32_t[3] that can be read as bytes/half-words/words
|
||||
* init32_t[0] PX4_CPU_UUID_ADDRESS[0] bits 31:0 (offset 0)
|
||||
* init32_t[1] PX4_CPU_UUID_ADDRESS[1] bits 63:32 (offset 4)
|
||||
* init32_t[2] PX4_CPU_UUID_ADDRESS[3] bits 96:64 (offset 8)
|
||||
*
|
||||
* The original PX4 stm32 (legacy) based implementation **displayed** the
|
||||
* UUID as: ABCD EFGH IJKL
|
||||
* Where:
|
||||
* A was bit 31 and D was bit 0
|
||||
* E was bit 63 and H was bit 32
|
||||
* I was bit 95 and L was bit 64
|
||||
*
|
||||
* Since the string was used by some manufactures to identify the units
|
||||
* it must be preserved.
|
||||
*
|
||||
* For new targets moving forward we will use
|
||||
* IJKL EFGH ABCD
|
||||
*/
|
||||
# define PX4_CPU_UUID_BYTE_LENGTH 12
|
||||
# define PX4_CPU_UUID_WORD32_LENGTH (PX4_CPU_UUID_BYTE_LENGTH/sizeof(uint32_t))
|
||||
|
||||
/* The mfguid will be an array of bytes with
|
||||
* MSD @ index 0 - LSD @ index PX4_CPU_MFGUID_BYTE_LENGTH-1
|
||||
*
|
||||
* It will be converted to a string with the MSD on left and LSD on the right most position.
|
||||
*/
|
||||
# define PX4_CPU_MFGUID_BYTE_LENGTH PX4_CPU_UUID_BYTE_LENGTH
|
||||
|
||||
/* By not defining PX4_CPU_UUID_CORRECT_CORRELATION the following maintains the legacy incorrect order
|
||||
* used for selection of significant digits of the UUID in the PX4 code base.
|
||||
* This is done to avoid the ripple effects changing the IDs used on STM32 base platforms
|
||||
*/
|
||||
# if defined(PX4_CPU_UUID_CORRECT_CORRELATION)
|
||||
# define PX4_CPU_UUID_WORD32_UNIQUE_H 0 /* Least significant digits change the most */
|
||||
# define PX4_CPU_UUID_WORD32_UNIQUE_M 1 /* Middle significant digits */
|
||||
# define PX4_CPU_UUID_WORD32_UNIQUE_L 2 /* Most significant digits change the least */
|
||||
# else
|
||||
/* Legacy incorrect ordering */
|
||||
# define PX4_CPU_UUID_WORD32_UNIQUE_H 2 /* Most significant digits change the least */
|
||||
# define PX4_CPU_UUID_WORD32_UNIQUE_M 1 /* Middle significant digits */
|
||||
# define PX4_CPU_UUID_WORD32_UNIQUE_L 0 /* Least significant digits change the most */
|
||||
# endif
|
||||
|
||||
/* Separator nnn:nnn:nnnn 2 char per byte term */
|
||||
# define PX4_CPU_UUID_WORD32_FORMAT_SIZE (PX4_CPU_UUID_WORD32_LENGTH-1+(2*PX4_CPU_UUID_BYTE_LENGTH)+1)
|
||||
# define PX4_CPU_MFGUID_FORMAT_SIZE ((2*PX4_CPU_MFGUID_BYTE_LENGTH)+1)
|
||||
|
||||
# define px4_savepanic(fileno, context, length) stm32_bbsram_savepanic(fileno, context, length)
|
||||
|
||||
# define PX4_BUS_OFFSET 0 /* STM buses are 1 based no adjustment needed */
|
||||
# define px4_spibus_initialize(bus_num_1based) stm32_spibus_initialize(bus_num_1based)
|
||||
|
||||
# define px4_i2cbus_initialize(bus_num_1based) stm32_i2cbus_initialize(bus_num_1based)
|
||||
# define px4_i2cbus_uninitialize(pdev) stm32_i2cbus_uninitialize(pdev)
|
||||
|
||||
# define px4_arch_configgpio(pinset) stm32_configgpio(pinset)
|
||||
# define px4_arch_unconfiggpio(pinset) stm32_unconfiggpio(pinset)
|
||||
# define px4_arch_gpioread(pinset) stm32_gpioread(pinset)
|
||||
# define px4_arch_gpiowrite(pinset, value) stm32_gpiowrite(pinset, value)
|
||||
# define px4_arch_gpiosetevent(pinset,r,f,e,fp,a) stm32_gpiosetevent(pinset,r,f,e,fp,a)
|
||||
#endif // defined(CONFIG_ARCH_CHIP_STM32) || defined(CONFIG_ARCH_CHIP_STM32F7)
|
||||
|
||||
#if defined(CONFIG_ARCH_CHIP_KINETIS)
|
||||
# define PX4_SOC_ARCH_ID PX4_SOC_ARCH_ID_KINETISK66
|
||||
|
||||
# // Fixme: using ??
|
||||
# define PX4_BBSRAM_SIZE 2048
|
||||
# define PX4_BBSRAM_GETDESC_IOCTL 0
|
||||
# define PX4_NUMBER_I2C_BUSES KINETIS_NI2C
|
||||
|
||||
# define GPIO_OUTPUT_SET GPIO_OUTPUT_ONE
|
||||
# define GPIO_OUTPUT_CLEAR GPIO_OUTPUT_ZERO
|
||||
|
||||
# include <chip.h>
|
||||
# include <kinetis_spi.h>
|
||||
# include <kinetis_i2c.h>
|
||||
# include <kinetis_uid.h>
|
||||
|
||||
/* Kinetis defines the 128 bit UUID as
|
||||
* init32_t[4] that can be read as words
|
||||
* init32_t[0] PX4_CPU_UUID_ADDRESS[0] bits 127:96 (offset 0)
|
||||
* init32_t[1] PX4_CPU_UUID_ADDRESS[1] bits 95:64 (offset 4)
|
||||
* init32_t[2] PX4_CPU_UUID_ADDRESS[1] bits 63:32 (offset 8)
|
||||
* init32_t[3] PX4_CPU_UUID_ADDRESS[3] bits 31:0 (offset C)
|
||||
*
|
||||
* PX4 uses the words in bigendian order MSB to LSB
|
||||
* word [0] [1] [2] [3]
|
||||
* bits 127:96 95-64 63-32, 31-00,
|
||||
*/
|
||||
# define PX4_CPU_UUID_BYTE_LENGTH KINETIS_UID_SIZE
|
||||
# define PX4_CPU_UUID_WORD32_LENGTH (PX4_CPU_UUID_BYTE_LENGTH/sizeof(uint32_t))
|
||||
|
||||
/* The mfguid will be an array of bytes with
|
||||
* MSD @ index 0 - LSD @ index PX4_CPU_MFGUID_BYTE_LENGTH-1
|
||||
*
|
||||
* It will be converted to a string with the MSD on left and LSD on the right most position.
|
||||
*/
|
||||
# define PX4_CPU_MFGUID_BYTE_LENGTH PX4_CPU_UUID_BYTE_LENGTH
|
||||
|
||||
/* define common formating across all commands */
|
||||
|
||||
# define PX4_CPU_UUID_WORD32_FORMAT "%08x"
|
||||
# define PX4_CPU_UUID_WORD32_SEPARATOR ":"
|
||||
|
||||
# define PX4_CPU_UUID_WORD32_UNIQUE_H 3 /* Least significant digits change the most */
|
||||
# define PX4_CPU_UUID_WORD32_UNIQUE_M 2 /* Middle High significant digits */
|
||||
# define PX4_CPU_UUID_WORD32_UNIQUE_L 1 /* Middle Low significant digits */
|
||||
# define PX4_CPU_UUID_WORD32_UNIQUE_N 0 /* Most significant digits change the least */
|
||||
|
||||
/* Separator nnn:nnn:nnnn 2 char per byte term */
|
||||
# define PX4_CPU_UUID_WORD32_FORMAT_SIZE (PX4_CPU_UUID_WORD32_LENGTH-1+(2*PX4_CPU_UUID_BYTE_LENGTH)+1)
|
||||
# define PX4_CPU_MFGUID_FORMAT_SIZE ((2*PX4_CPU_MFGUID_BYTE_LENGTH)+1)
|
||||
|
||||
# define kinetis_bbsram_savepanic(fileno, context, length) (0) // todo:Not implemented yet
|
||||
|
||||
# define px4_savepanic(fileno, context, length) kinetis_bbsram_savepanic(fileno, context, length)
|
||||
|
||||
/* bus_num is zero based on kinetis and must be translated from the legacy one based */
|
||||
|
||||
# define PX4_BUS_OFFSET 1 /* Kinetis buses are 0 based and adjustment is needed */
|
||||
|
||||
# define px4_spibus_initialize(bus_num_1based) kinetis_spibus_initialize(PX4_BUS_NUMBER_FROM_PX4(bus_num_1based))
|
||||
|
||||
# define px4_i2cbus_initialize(bus_num_1based) kinetis_i2cbus_initialize(PX4_BUS_NUMBER_FROM_PX4(bus_num_1based))
|
||||
# define px4_i2cbus_uninitialize(pdev) kinetis_i2cbus_uninitialize(pdev)
|
||||
|
||||
# define px4_arch_configgpio(pinset) kinetis_pinconfig(pinset)
|
||||
# define px4_arch_unconfiggpio(pinset)
|
||||
# define px4_arch_gpioread(pinset) kinetis_gpioread(pinset)
|
||||
# define px4_arch_gpiowrite(pinset, value) kinetis_gpiowrite(pinset, value)
|
||||
|
||||
/* kinetis_gpiosetevent is not implemented and will need to be added */
|
||||
|
||||
# define px4_arch_gpiosetevent(pinset,r,f,e,fp,a) kinetis_gpiosetevent(pinset,r,f,e,fp,a)
|
||||
# endif
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
__END_DECLS
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user