kopia lustrzana https://github.com/cariboulabs/cariboulite
Kernel Driver: module timeout issue when switching streaming channels. caused due to waiting to a timeout on the previous channel. That
stream stopped thus the buffer never filled up. solved by aboting the waiting semaphore on channel switch SMI: fixed low sample rate timeouts and a function for timeout calculation on read Radio: FPGA soft reset on start caused faulty operation. needs investigation. Radio: removed redundant sleeps Various bug fixes.pull/146/head
rodzic
774f1862d1
commit
a698dcf02a
|
@ -92,6 +92,10 @@ struct bcm2835_smi_dev_instance
|
|||
wait_queue_head_t poll_event;
|
||||
bool readable;
|
||||
bool writeable;
|
||||
bool reader_thread_running;
|
||||
bool writer_thread_running;
|
||||
bool reader_waiting_sema;
|
||||
bool writer_waiting_sema;
|
||||
};
|
||||
|
||||
|
||||
|
@ -211,6 +215,12 @@ static void set_state(smi_stream_state_en state)
|
|||
{
|
||||
dev_info(inst->dev, "Set STREAMING_STATUS = %d, cur_addr = %d", state, inst->cur_address);
|
||||
inst->address_changed = 1;
|
||||
|
||||
// abort the current timed out waiting on the current channel
|
||||
if (inst->smi_inst != NULL && inst->reader_waiting_sema)
|
||||
{
|
||||
up(&inst->smi_inst->bounce.callback_sem);
|
||||
}
|
||||
}
|
||||
|
||||
inst->state = state;
|
||||
|
@ -629,17 +639,14 @@ int reader_thread_stream_function(void *pv)
|
|||
s64 t1, t2, t3;
|
||||
|
||||
dev_info(inst->dev, "Enterred reader thread");
|
||||
inst->reader_thread_running = true;
|
||||
|
||||
while(!kthread_should_stop())
|
||||
{
|
||||
// check if the streaming state is on, if not, sleep and check again
|
||||
if (inst->state != smi_stream_rx_channel_0 && inst->state != smi_stream_rx_channel_1)
|
||||
{
|
||||
//mutex_lock(&inst->read_lock);
|
||||
//kfifo_reset(&inst->rx_fifo);
|
||||
//mutex_unlock(&inst->read_lock);
|
||||
|
||||
msleep(5);
|
||||
msleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -647,7 +654,7 @@ int reader_thread_stream_function(void *pv)
|
|||
// sync smi address
|
||||
if (inst->address_changed)
|
||||
{
|
||||
bcm2835_smi_set_address(inst->smi_inst, inst->cur_address);
|
||||
bcm2835_smi_set_address(inst->smi_inst, inst->cur_address);
|
||||
inst->address_changed = 0;
|
||||
}
|
||||
|
||||
|
@ -657,7 +664,7 @@ int reader_thread_stream_function(void *pv)
|
|||
count = stream_smi_user_dma(inst->smi_inst, DMA_DEV_TO_MEM, &bounce, current_dma_buffer);
|
||||
if (count != DMA_BOUNCE_BUFFER_SIZE || bounce == NULL)
|
||||
{
|
||||
dev_err(inst->dev, "stream_smi_user_dma returned illegal count = %d", count);
|
||||
dev_err(inst->dev, "stream_smi_user_dma returned illegal count = %d, buff_num = %d", count, current_dma_buffer);
|
||||
spin_lock(&inst->smi_inst->transaction_lock);
|
||||
dmaengine_terminate_sync(inst->smi_inst->dma_chan);
|
||||
spin_unlock(&inst->smi_inst->transaction_lock);
|
||||
|
@ -692,41 +699,31 @@ int reader_thread_stream_function(void *pv)
|
|||
// timeout. This means that we didn't get enough data into the buffer during this period. we shall
|
||||
// "continue" and try again
|
||||
start = ktime_get();
|
||||
while (1)
|
||||
// wait for completion
|
||||
inst->reader_waiting_sema = true;
|
||||
if (down_timeout(&bounce->callback_sem, msecs_to_jiffies(1000)))
|
||||
{
|
||||
// wait for completion, but if not complete (timeout) - nevermind,
|
||||
// try to wait more, unless someone tells us to stop
|
||||
if (down_timeout(&bounce->callback_sem, msecs_to_jiffies(1000)))
|
||||
{
|
||||
dev_info(inst->dev, "Reader DMA bounce timed out");
|
||||
spin_lock(&inst->smi_inst->transaction_lock);
|
||||
dmaengine_terminate_sync(inst->smi_inst->dma_chan);
|
||||
spin_unlock(&inst->smi_inst->transaction_lock);
|
||||
}
|
||||
else
|
||||
{
|
||||
//--------------------------------------------------------
|
||||
// Switch the buffers
|
||||
current_dma_buffer = 1-current_dma_buffer;
|
||||
break;
|
||||
}
|
||||
|
||||
// after each timeout check if we are still entitled to keep trying
|
||||
// if not, shut down the DMA transaction and continue empty loop
|
||||
if (inst->state != smi_stream_rx_channel_0 && inst->state != smi_stream_rx_channel_1)
|
||||
{
|
||||
spin_lock(&inst->smi_inst->transaction_lock);
|
||||
dmaengine_terminate_sync(inst->smi_inst->dma_chan);
|
||||
spin_unlock(&inst->smi_inst->transaction_lock);
|
||||
break;
|
||||
}
|
||||
dev_info(inst->dev, "Reader DMA bounce timed out");
|
||||
spin_lock(&inst->smi_inst->transaction_lock);
|
||||
dmaengine_terminate_sync(inst->smi_inst->dma_chan);
|
||||
spin_unlock(&inst->smi_inst->transaction_lock);
|
||||
}
|
||||
else
|
||||
{
|
||||
//--------------------------------------------------------
|
||||
// Switch the buffers
|
||||
current_dma_buffer = 1-current_dma_buffer;
|
||||
}
|
||||
inst->reader_waiting_sema = false;
|
||||
|
||||
t3 = ktime_to_ns(ktime_sub(ktime_get(), start));
|
||||
|
||||
//dev_info(inst->dev, "TIMING (1,2,3): %lld %lld %lld %d", (long long)t1, (long long)t2, (long long)t3, current_dma_buffer);
|
||||
}
|
||||
|
||||
dev_info(inst->dev, "Left reader thread");
|
||||
inst->reader_thread_running = false;
|
||||
inst->reader_waiting_sema = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -739,6 +736,7 @@ int writer_thread_stream_function(void *pv)
|
|||
int num_bytes = 0;
|
||||
int num_copied = 0;
|
||||
dev_info(inst->dev, "Enterred writer thread");
|
||||
inst->writer_thread_running = true;
|
||||
|
||||
while(!kthread_should_stop())
|
||||
{
|
||||
|
@ -752,7 +750,7 @@ int writer_thread_stream_function(void *pv)
|
|||
// sync smi address
|
||||
if (inst->address_changed)
|
||||
{
|
||||
bcm2835_smi_set_address(inst->smi_inst, inst->cur_address);
|
||||
bcm2835_smi_set_address(inst->smi_inst, inst->cur_address);
|
||||
inst->address_changed = 0;
|
||||
}
|
||||
|
||||
|
@ -794,6 +792,7 @@ int writer_thread_stream_function(void *pv)
|
|||
}
|
||||
|
||||
// Wait for current chunk to complete
|
||||
inst->writer_waiting_sema = true;
|
||||
if (down_timeout(&bounce->callback_sem, msecs_to_jiffies(1000)))
|
||||
{
|
||||
dev_err(inst->dev, "Writer DMA bounce timed out");
|
||||
|
@ -801,6 +800,7 @@ int writer_thread_stream_function(void *pv)
|
|||
dmaengine_terminate_sync(inst->smi_inst->dma_chan);
|
||||
spin_unlock(&inst->smi_inst->transaction_lock);
|
||||
}
|
||||
inst->writer_waiting_sema = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -811,6 +811,8 @@ int writer_thread_stream_function(void *pv)
|
|||
}
|
||||
|
||||
dev_info(inst->dev, "Left writer thread");
|
||||
inst->writer_thread_running = false;
|
||||
inst->writer_waiting_sema = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1191,6 +1193,10 @@ static int smi_stream_dev_probe(struct platform_device *pdev)
|
|||
init_waitqueue_head(&inst->poll_event);
|
||||
inst->readable = false;
|
||||
inst->writeable = false;
|
||||
inst->reader_thread_running = false;
|
||||
inst->writer_thread_running = false;
|
||||
inst->reader_waiting_sema = false;
|
||||
inst->writer_waiting_sema = false;
|
||||
mutex_init(&inst->read_lock);
|
||||
mutex_init(&inst->write_lock);
|
||||
|
||||
|
|
|
@ -184,26 +184,25 @@ int caribou_fpga_program_to_fpga(caribou_fpga_st* dev, unsigned char *buffer, si
|
|||
|
||||
while (prog_retries--)
|
||||
{
|
||||
if (caribou_prog_configure_from_buffer(&dev->prog_dev, buffer, len) == 0)
|
||||
if (caribou_prog_configure_from_buffer(&dev->prog_dev, buffer, len) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//caribou_fpga_soft_reset(dev);
|
||||
io_utils_usleep(100000);
|
||||
|
||||
caribou_fpga_get_status(dev, NULL);
|
||||
if (dev->status == caribou_fpga_status_operational)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (prog_retries == 0)
|
||||
{
|
||||
ZF_LOGE("Programming failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
caribou_fpga_soft_reset(dev);
|
||||
io_utils_usleep(100000);
|
||||
|
||||
caribou_fpga_get_status(dev, NULL);
|
||||
if (dev->status == caribou_fpga_status_not_programmed)
|
||||
{
|
||||
ZF_LOGE("Programming failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -569,6 +569,7 @@ int caribou_smi_init(caribou_smi_st* dev,
|
|||
|
||||
dev->debug_mode = caribou_smi_none;
|
||||
dev->invert_iq = false;
|
||||
dev->sample_rate = CARIBOU_SMI_SAMPLE_RATE;
|
||||
dev->initialized = 1;
|
||||
|
||||
return 0;
|
||||
|
@ -585,6 +586,23 @@ int caribou_smi_close (caribou_smi_st* dev)
|
|||
return close (dev->filedesc);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
void caribou_smi_set_sample_rate(caribou_smi_st* dev, uint32_t sample_rate)
|
||||
{
|
||||
if (sample_rate < 100000)
|
||||
{
|
||||
dev->sample_rate = 100000;
|
||||
}
|
||||
else if (sample_rate > CARIBOU_SMI_SAMPLE_RATE)
|
||||
{
|
||||
dev->sample_rate = CARIBOU_SMI_SAMPLE_RATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dev->sample_rate = sample_rate;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
void caribou_smi_set_debug_mode(caribou_smi_st* dev, caribou_smi_debug_mode_en mode)
|
||||
{
|
||||
|
@ -597,6 +615,14 @@ void caribou_smi_invert_iq(caribou_smi_st* dev, bool invert)
|
|||
dev->invert_iq = invert;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
static int caribou_smi_calc_read_timeout(uint32_t sample_rate, size_t len)
|
||||
{
|
||||
uint32_t to_millisec = (2 * len * 1000) / sample_rate;
|
||||
if (to_millisec < 1) to_millisec = 1;
|
||||
return to_millisec;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
int caribou_smi_read(caribou_smi_st* dev, caribou_smi_channel_en channel,
|
||||
caribou_smi_sample_complex_int16* samples,
|
||||
|
@ -607,9 +633,8 @@ int caribou_smi_read(caribou_smi_st* dev, caribou_smi_channel_en channel,
|
|||
caribou_smi_sample_meta* meta_offset = metadata;
|
||||
size_t left_to_read = length_samples * CARIBOU_SMI_BYTES_PER_SAMPLE; // in bytes
|
||||
size_t read_so_far = 0; // in samples
|
||||
uint32_t to_millisec = (2 * dev->native_batch_len * 1000) / CARIBOU_SMI_SAMPLE_RATE;
|
||||
if (to_millisec < 2) to_millisec = 2;
|
||||
|
||||
uint32_t to_millisec = caribou_smi_calc_read_timeout(dev->sample_rate, dev->native_batch_len);
|
||||
|
||||
while (left_to_read)
|
||||
{
|
||||
if (sample_offset) sample_offset = samples + read_so_far;
|
||||
|
@ -617,6 +642,8 @@ int caribou_smi_read(caribou_smi_st* dev, caribou_smi_channel_en channel,
|
|||
|
||||
// current_read_len in bytes
|
||||
size_t current_read_len = ((left_to_read > dev->native_batch_len) ? dev->native_batch_len : left_to_read);
|
||||
|
||||
to_millisec = caribou_smi_calc_read_timeout(dev->sample_rate, current_read_len);
|
||||
int ret = caribou_smi_timeout_read(dev, dev->read_temp_buffer, current_read_len, to_millisec);
|
||||
if (ret < 0)
|
||||
{
|
||||
|
|
|
@ -63,6 +63,7 @@ typedef struct
|
|||
int initialized;
|
||||
int filedesc;
|
||||
size_t native_batch_len;
|
||||
uint32_t sample_rate;
|
||||
smi_stream_state_en state;
|
||||
|
||||
uint8_t *read_temp_buffer;
|
||||
|
@ -95,6 +96,7 @@ int caribou_smi_write(caribou_smi_st* dev, caribou_smi_channel_en channel,
|
|||
size_t caribou_smi_get_native_batch_samples(caribou_smi_st* dev);
|
||||
|
||||
void caribou_smi_setup_ios(caribou_smi_st* dev);
|
||||
void caribou_smi_set_sample_rate(caribou_smi_st* dev, uint32_t sample_rate);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -36,14 +36,11 @@ int cariboulite_radio_init(cariboulite_radio_state_st* radio, sys_st *sys, carib
|
|||
radio->smi_channel_id = GET_SMI_CH(type);
|
||||
|
||||
// activation of the channel
|
||||
if (cariboulite_radio_activate_channel(radio, cariboulite_channel_dir_rx, true) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
usleep(10000);
|
||||
cariboulite_radio_activate_channel(radio, cariboulite_channel_dir_rx, true);
|
||||
usleep(1000);
|
||||
cariboulite_radio_activate_channel(radio, cariboulite_channel_dir_rx, false);
|
||||
|
||||
return cariboulite_radio_activate_channel(radio, cariboulite_channel_dir_rx, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
|
@ -245,6 +242,22 @@ int cariboulite_radio_set_rx_samp_cutoff(cariboulite_radio_state_st* radio,
|
|||
at86rf215_radio_set_rx_bandwidth_sampling(&radio->sys->modem, GET_MODEM_CH(radio->type), &cfg);
|
||||
radio->rx_fs = rx_sample_rate;
|
||||
radio->rx_fcut = rx_cutoff;
|
||||
|
||||
// setup the smi sample rate for timeout
|
||||
uint32_t sample_rate = 4000000;
|
||||
switch(rx_sample_rate)
|
||||
{
|
||||
at86rf215_radio_rx_sample_rate_4000khz: sample_rate = 4000000; break;
|
||||
at86rf215_radio_rx_sample_rate_2000khz: sample_rate = 2000000; break;
|
||||
at86rf215_radio_rx_sample_rate_1333khz: sample_rate = 1333000; break;
|
||||
at86rf215_radio_rx_sample_rate_1000khz: sample_rate = 1000000; break;
|
||||
at86rf215_radio_rx_sample_rate_800khz: sample_rate = 800000; break;
|
||||
at86rf215_radio_rx_sample_rate_666khz: sample_rate = 666000; break;
|
||||
at86rf215_radio_rx_sample_rate_500khz: sample_rate = 500000; break;
|
||||
at86rf215_radio_rx_sample_rate_400khz: sample_rate = 400000; break;
|
||||
}
|
||||
|
||||
caribou_smi_set_sample_rate(&radio->sys->smi, sample_rate);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -864,13 +877,12 @@ int cariboulite_radio_activate_channel(cariboulite_radio_state_st* radio,
|
|||
|
||||
// then deactivate the modem's stream
|
||||
cariboulite_radio_set_modem_state(radio, at86rf215_radio_state_cmd_trx_off);
|
||||
|
||||
// if we deactivate, first shut off the smi stream
|
||||
ret = caribou_smi_set_driver_streaming_state(&radio->sys->smi, smi_stream_idle);
|
||||
|
||||
// DEACTIVATION
|
||||
if (activate == false)
|
||||
if (!activate)
|
||||
{
|
||||
// if we deactivate, first shut off the smi stream
|
||||
ret = caribou_smi_set_driver_streaming_state(&radio->sys->smi, smi_stream_idle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -901,7 +913,7 @@ int cariboulite_radio_activate_channel(cariboulite_radio_state_st* radio,
|
|||
// RX on both channels looks the same
|
||||
if (radio->channel_direction == cariboulite_channel_dir_rx)
|
||||
{
|
||||
// after modem is activated turn on the the smi stream
|
||||
// Setup the IQ stream properties
|
||||
smi_stream_state_en smi_state = smi_stream_idle;
|
||||
if (radio->smi_channel_id == caribou_smi_channel_900)
|
||||
smi_state = smi_stream_rx_channel_0;
|
||||
|
@ -918,15 +930,15 @@ int cariboulite_radio_activate_channel(cariboulite_radio_state_st* radio,
|
|||
.clock_skew = at86rf215_iq_clock_data_skew_4_906ns,
|
||||
};
|
||||
at86rf215_setup_iq_if(&radio->sys->modem, &modem_iq_config);
|
||||
|
||||
|
||||
// configure FPGA with the correct rx channel
|
||||
caribou_fpga_set_smi_channel (&radio->sys->fpga, radio->type == cariboulite_channel_s1g? caribou_fpga_smi_channel_0 : caribou_fpga_smi_channel_1);
|
||||
caribou_fpga_set_io_ctrl_dig (&radio->sys->fpga, radio->type == cariboulite_channel_s1g? 0 : 1, 0);
|
||||
//caribou_fpga_set_io_ctrl_dig (&radio->sys->fpga, radio->type == cariboulite_channel_s1g? 0 : 1, 0);
|
||||
|
||||
//usleep(5000);
|
||||
// turn on the modem RX
|
||||
cariboulite_radio_set_modem_state(radio, at86rf215_radio_state_cmd_rx);
|
||||
usleep(20000);
|
||||
|
||||
// apply the state
|
||||
// turn on the SMI stream
|
||||
if (caribou_smi_set_driver_streaming_state(&radio->sys->smi, smi_state) != 0)
|
||||
{
|
||||
ZF_LOGD("Failed to configure modem with cmd_rx");
|
||||
|
|
|
@ -387,9 +387,9 @@ int cariboulite_init_submodules (sys_st* sys)
|
|||
// Print the SPI information
|
||||
//io_utils_spi_print_setup(&sys->spi_dev);
|
||||
|
||||
// Initialize the two Radio High-Level devices
|
||||
cariboulite_radio_init(&sys->radio_low, sys, cariboulite_channel_s1g);
|
||||
cariboulite_radio_init(&sys->radio_high, sys, cariboulite_channel_6g);
|
||||
// Initialize the two Radio High-Level devices
|
||||
cariboulite_radio_init(&sys->radio_low, sys, cariboulite_channel_s1g);
|
||||
cariboulite_radio_init(&sys->radio_high, sys, cariboulite_channel_6g);
|
||||
|
||||
cariboulite_radio_set_rx_samp_cutoff(&sys->radio_low, at86rf215_radio_rx_sample_rate_4000khz, at86rf215_radio_rx_f_cut_half_fs);
|
||||
cariboulite_radio_set_tx_samp_cutoff(&sys->radio_low, at86rf215_radio_rx_sample_rate_4000khz, at86rf215_radio_rx_f_cut_half_fs);
|
||||
|
@ -632,7 +632,7 @@ int cariboulite_init_driver_minimal(sys_st *sys, hat_board_info_st *info, bool p
|
|||
}
|
||||
if (sys->reset_fpga_on_startup)
|
||||
{
|
||||
caribou_fpga_soft_reset(&sys->fpga);
|
||||
//caribou_fpga_soft_reset(&sys->fpga);
|
||||
}
|
||||
|
||||
// Reading the configuration from the FPGA (resistor set)
|
||||
|
|
Ładowanie…
Reference in New Issue