2019-09-30 08:45 AM
I'm trying to write blocks of ADC Conversions using DMA from the STM32F46 Dsicovery board and I'm having issues writing to the SD card when HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) is called.
I'm running a 500KHz timer to trigger my ADC and I calculate I'll need roughly 21333 samples to fill a 32KB buffer. Based on benchmarking my SD card for random writes, I estimate this will take around 20ms. My ADC buffer will require about 42.66ms to fill up so I have some time to play with before the next set of conversions are ready.
But for some reason I'm unable to write to the SD card at all. My Main code is shown below:
#define BUFFER_LENGTH 21333
int main(void)
{
MX_GPIO_Init();
MX_DMA_Init();
MX_SDMMC1_SD_Init();
MX_FATFS_Init();
MX_ADC3_Init();
MX_TIM1_Init();
/* Start Timer */
if (HAL_TIM_Base_Start_IT(&htim1) != HAL_OK)
{
Error_Handler();
}
/* Start ADC */
if(HAL_ADC_Start_DMA(&hadc3, (uint32_t*)&adc_values, BUFFER_LENGTH) != HAL_OK)
{
Error_Handler();
}
while (1)
{
}
}
And the Conversion Complete Callback goes something like:
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance == ADC3)
{
// This doesn't work
if(f_mount(&myFatFS, SDPath, 1) == FR_OK)
{
char myFileName[] = "DMA.txt";
if(f_open(&myFile, myFileName, FA_WRITE | FA_CREATE_ALWAYS) == FR_OK)
{
res = f_write(&myFile, (uint8_t *)adc_values, BUFFER_LENGTH * 2, &myBytes);
f_close(&myFile);
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_1, GPIO_PIN_SET); // Set LED once compete
}
}
}
}
This doesn't work and the file is not created nor is the SD Card mounted. What would be the best way to solve this issue. There are also a few things I'm unclear about on this as well and would appreciate if I could get some answers
2019-09-30 09:10 AM
Callbacks are called under interrupt context, you should buffer the data and leave, not doing anything that will block.
Personally, if you're not doing multi-threaded stuff, put the writing in the main() loop, do f_open/f_close once, and f_write a holding buffer when you accumulate enough data. The balance of buffer sizes will depend on expected through-put. The ADC can operate on a smaller buffer that it ping-pongs between, and fills a larger buffer, or can do it in-place with a larger buffer say 32K or 64K, flagging a flush of the inactive upper/lower half to a secondary task.
>>What penalties could be incurred on the lifespan of the card..
Likely to be significant, the cards are typically juggling a pool of 128KB erase blocks, as the cards get fuller the availability will drop, and while the wear is spread around this open-write-close methodology will be detrimental. Caching and lazy writing can diminish these issues significantly, but does increase complexity. Pick your battles.