mirror of https://github.com/ArduPilot/ardupilot
AP_HAL_ChibiOS: add support for saving and restoring SCK pin state
when SPI goes into undefined state during reset
This commit is contained in:
parent
6a97817fa6
commit
829fcf5f33
|
@ -69,6 +69,7 @@ static const struct SPIDriverInfo {
|
||||||
uint8_t busid; // used for device IDs in parameters
|
uint8_t busid; // used for device IDs in parameters
|
||||||
uint8_t dma_channel_rx;
|
uint8_t dma_channel_rx;
|
||||||
uint8_t dma_channel_tx;
|
uint8_t dma_channel_tx;
|
||||||
|
ioline_t sck_line;
|
||||||
} spi_devices[] = { HAL_SPI_BUS_LIST };
|
} spi_devices[] = { HAL_SPI_BUS_LIST };
|
||||||
|
|
||||||
// device list comes from hwdef.dat
|
// device list comes from hwdef.dat
|
||||||
|
@ -86,6 +87,8 @@ SPIBus::SPIBus(uint8_t _bus) :
|
||||||
FUNCTOR_BIND_MEMBER(&SPIBus::dma_allocate, void, Shared_DMA *),
|
FUNCTOR_BIND_MEMBER(&SPIBus::dma_allocate, void, Shared_DMA *),
|
||||||
FUNCTOR_BIND_MEMBER(&SPIBus::dma_deallocate, void, Shared_DMA *));
|
FUNCTOR_BIND_MEMBER(&SPIBus::dma_deallocate, void, Shared_DMA *));
|
||||||
|
|
||||||
|
// remember the SCK line for stop_peripheral()/start_peripheral()
|
||||||
|
sck_mode = palReadLineMode(spi_devices[bus].sck_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -103,10 +106,7 @@ void SPIBus::dma_deallocate(Shared_DMA *ctx)
|
||||||
{
|
{
|
||||||
chMtxLock(&dma_lock);
|
chMtxLock(&dma_lock);
|
||||||
// another non-SPI peripheral wants one of our DMA channels
|
// another non-SPI peripheral wants one of our DMA channels
|
||||||
if (spi_started) {
|
stop_peripheral();
|
||||||
spiStop(spi_devices[bus].driver);
|
|
||||||
spi_started = false;
|
|
||||||
}
|
|
||||||
chMtxUnlock(&dma_lock);
|
chMtxUnlock(&dma_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,6 +339,46 @@ bool SPIDevice::adjust_periodic_callback(AP_HAL::Device::PeriodicHandle h, uint3
|
||||||
return bus.adjust_timer(h, period_usec);
|
return bus.adjust_timer(h, period_usec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
stop the SPI peripheral and set the SCK line as a GPIO to prevent the clock
|
||||||
|
line floating while we are waiting for the next spiStart()
|
||||||
|
*/
|
||||||
|
void SPIBus::stop_peripheral(void)
|
||||||
|
{
|
||||||
|
if (!spi_started) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto &sbus = spi_devices[bus];
|
||||||
|
if (spi_mode == SPIDEV_MODE0 || spi_mode == SPIDEV_MODE1) {
|
||||||
|
// Clock polarity is 0, so we need to set the clock line low before spi reset
|
||||||
|
palClearLine(sbus.sck_line);
|
||||||
|
} else {
|
||||||
|
// Clock polarity is 1, so we need to set the clock line high before spi reset
|
||||||
|
palSetLine(sbus.sck_line);
|
||||||
|
}
|
||||||
|
palSetLineMode(sbus.sck_line, PAL_MODE_OUTPUT_PUSHPULL);
|
||||||
|
spiStop(sbus.driver);
|
||||||
|
spi_started = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
start the SPI peripheral and restore the IO mode of the SCK line
|
||||||
|
*/
|
||||||
|
void SPIBus::start_peripheral(void)
|
||||||
|
{
|
||||||
|
if (spi_started) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* start driver and setup transfer parameters */
|
||||||
|
spiStart(spi_devices[bus].driver, &spicfg);
|
||||||
|
|
||||||
|
// restore sck pin mode from stop_peripheral()
|
||||||
|
palSetLineMode(spi_devices[bus].sck_line, sck_mode);
|
||||||
|
|
||||||
|
spi_started = true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
used to acquire bus and (optionally) assert cs
|
used to acquire bus and (optionally) assert cs
|
||||||
*/
|
*/
|
||||||
|
@ -380,12 +420,9 @@ bool SPIDevice::acquire_bus(bool set, bool skip_cs)
|
||||||
bus.spicfg.cr1 = (uint16_t)(freq_flag | device_desc.mode);
|
bus.spicfg.cr1 = (uint16_t)(freq_flag | device_desc.mode);
|
||||||
bus.spicfg.cr2 = 0;
|
bus.spicfg.cr2 = 0;
|
||||||
#endif
|
#endif
|
||||||
if (bus.spi_started) {
|
bus.spi_mode = device_desc.mode;
|
||||||
spiStop(spi_devices[device_desc.bus].driver);
|
bus.stop_peripheral();
|
||||||
bus.spi_started = false;
|
bus.start_peripheral();
|
||||||
}
|
|
||||||
spiStart(spi_devices[device_desc.bus].driver, &bus.spicfg); /* Setup transfer parameters. */
|
|
||||||
bus.spi_started = true;
|
|
||||||
if(!skip_cs) {
|
if(!skip_cs) {
|
||||||
spiSelectI(spi_devices[device_desc.bus].driver); /* Slave Select assertion. */
|
spiSelectI(spi_devices[device_desc.bus].driver); /* Slave Select assertion. */
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,6 @@ public:
|
||||||
SPIConfig spicfg;
|
SPIConfig spicfg;
|
||||||
void dma_allocate(Shared_DMA *ctx);
|
void dma_allocate(Shared_DMA *ctx);
|
||||||
void dma_deallocate(Shared_DMA *ctx);
|
void dma_deallocate(Shared_DMA *ctx);
|
||||||
bool spi_started;
|
|
||||||
uint8_t slowdown;
|
uint8_t slowdown;
|
||||||
|
|
||||||
// we need an additional lock in the dma_allocate and
|
// we need an additional lock in the dma_allocate and
|
||||||
|
@ -43,6 +42,19 @@ public:
|
||||||
// have two DMA channels that we are handling with the shared_dma
|
// have two DMA channels that we are handling with the shared_dma
|
||||||
// code
|
// code
|
||||||
mutex_t dma_lock;
|
mutex_t dma_lock;
|
||||||
|
|
||||||
|
// store the last spi mode for stop_peripheral()
|
||||||
|
uint32_t spi_mode;
|
||||||
|
|
||||||
|
// start and stop the hardware peripheral
|
||||||
|
void start_peripheral(void);
|
||||||
|
void stop_peripheral(void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool spi_started;
|
||||||
|
|
||||||
|
// mode line for SCK pin
|
||||||
|
iomode_t sck_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SPIDesc {
|
struct SPIDesc {
|
||||||
|
|
|
@ -1403,26 +1403,26 @@ def write_SPI_table(f):
|
||||||
f.write("\n")
|
f.write("\n")
|
||||||
|
|
||||||
|
|
||||||
def write_SPI_config(f):
|
def write_SPI_config(self, f):
|
||||||
'''write SPI config defines'''
|
'''write SPI config defines'''
|
||||||
global spi_list
|
for t in list(self.bytype.keys()) + list(self.alttype.keys()):
|
||||||
for t in list(bytype.keys()) + list(alttype.keys()):
|
|
||||||
if t.startswith('SPI'):
|
if t.startswith('SPI'):
|
||||||
spi_list.append(t)
|
self.spi_list.append(t)
|
||||||
spi_list = sorted(spi_list)
|
self.spi_list = sorted(self.spi_list)
|
||||||
if len(spi_list) == 0:
|
if len(self.spi_list) == 0:
|
||||||
f.write('#define HAL_USE_SPI FALSE\n')
|
f.write('#define HAL_USE_SPI FALSE\n')
|
||||||
return
|
return
|
||||||
devlist = []
|
devlist = []
|
||||||
for dev in spi_list:
|
for dev in self.spi_list:
|
||||||
n = int(dev[3:])
|
n = int(dev[3:])
|
||||||
devlist.append('HAL_SPI%u_CONFIG' % n)
|
devlist.append('HAL_SPI%u_CONFIG' % n)
|
||||||
|
sck_pin = self.bylabel['SPI%s_SCK' % n]
|
||||||
|
sck_line = 'PAL_LINE(GPIO%s,%uU)' % (sck_pin.port, sck_pin.pin)
|
||||||
f.write(
|
f.write(
|
||||||
'#define HAL_SPI%u_CONFIG { &SPID%u, %u, STM32_SPI_SPI%u_DMA_STREAMS }\n'
|
'#define HAL_SPI%u_CONFIG { &SPID%u, %u, STM32_SPI_SPI%u_DMA_STREAMS, %s }\n'
|
||||||
% (n, n, n, n))
|
% (n, n, n, n, sck_line))
|
||||||
f.write('#define HAL_SPI_BUS_LIST %s\n\n' % ','.join(devlist))
|
f.write('#define HAL_SPI_BUS_LIST %s\n\n' % ','.join(devlist))
|
||||||
write_SPI_table(f)
|
self.write_SPI_table(f)
|
||||||
|
|
||||||
|
|
||||||
def write_QSPI_table(f):
|
def write_QSPI_table(f):
|
||||||
'''write SPI device table'''
|
'''write SPI device table'''
|
||||||
|
|
Loading…
Reference in New Issue