Stm32f4 dma m2m - dma

I'm using STM32F407VG Discovery Board and I've issue with DMA memory to memory transfer. I want to copy 32 bytes of data from one place in memory to other using DMA by writing copy_dma() function. In while loop i'm checking Transfer Complete flag but DMA never returns it. I want to ask where i'm making mistake? Maybe something in configuration is wrong. I'm using Standart Peripheral Libraries. Here's my code.
#include "stm32f4xx.h"
#define BUFFER_SIZE 32
uint8_t src_buffer[BUFFER_SIZE];
uint8_t dst_buffer[BUFFER_SIZE];
void copy_dma(void);
int main(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
int i;
DMA_InitTypeDef dma;
DMA_DeInit(DMA1_Stream4);
DMA_StructInit(&dma);
dma.DMA_Channel = DMA_Channel_1;
dma.DMA_PeripheralBaseAddr = (uint32_t)src_buffer;
dma.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
dma.DMA_Memory0BaseAddr = (uint32_t)dst_buffer;
dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma.DMA_BufferSize = BUFFER_SIZE;
dma.DMA_DIR = DMA_DIR_MemoryToMemory;
dma.DMA_FIFOMode = DMA_FIFOMode_Disable;
dma.DMA_MemoryBurst = DMA_MemoryBurst_Single;
dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
dma.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
dma.DMA_Mode = DMA_Mode_Normal;
dma.DMA_Priority = DMA_Priority_High;
DMA_Init(DMA1_Stream4, &dma);
for (i = 0; i < BUFFER_SIZE; i++) {
src_buffer[i] = 100 + i;
}
copy_dma();
while(1) {
}
}
void copy_dma(void) {
DMA_Cmd(DMA1_Stream4, ENABLE);
while (DMA_GetFlagStatus(DMA1_Stream4, DMA_FLAG_TCIF4) == RESET);
}

In app note "Using the STM32F2 and STM32F4 DMA controller"(http://stm32.eefocus.com/download/index.php?act=down&id=6312)
is mentioned:
"Memory to memory (only DMA2 is able to do such transfer, in this mode, the circular and direct modes are not allowed.)"
So, try to use DMA2.

In addition to Mariusz Górka's awnser:
When using the DMA you need to know which memory region you are using. The stm32f4 has a memory section called Core Coupled Memory (CCM). The DMA does not have access to this region.
Check your map file and make sure your buffers are not in the region 0x10000000 - 0x1000FFFF.

Related

GRUB memory map gives me weird values

I am trying to use grub in order to get the memory map, instead of going through the bios route. The problem is that grub seems to be giving me very weird values for some reason. Can anyone help with this?
Relevant code:
This is how I parse the mmap
void mm_init(mmap_entry_t *mmap_addr, uint32_t length)
{
mmap = mmap_addr;
/* Loop through mmap */
printk("-- Scanning memory map --");
for (size_t i = 0; mmap < (mmap_addr + length); i++) {
/* RAM is available! */
if (mmap->type == 1) {
uint64_t starting_addr = (((uint64_t) mmap->base_addr_high) << 32) | ((uint64_t) mmap->base_addr_low);
uint64_t length = (((uint64_t) mmap->length_high) << 32) | ((uint64_t) mmap->length_low);
printk("Found segment starting from 0x%x, with a length of %i", starting_addr, length);
}
/* Next entry */
mmap = (mmap_entry_t *) ((uint32_t) mmap + mmap->size + sizeof(mmap->size));
}
}
This is my mmap_entry_t struct (not the one in multiboot.h):
struct mmap_entry {
uint32_t size;
uint32_t base_addr_low, base_addr_high;
uint32_t length_low, length_high;
uint8_t type;
} __attribute__((packed));
typedef struct mmap_entry mmap_entry_t;
And this is how I call mm_init()
/* Kernel main function */
void kmain(multiboot_info_t *info)
{
/* Check if grub can give us a memory map */
/* TODO: Detect manually */
if (!(info->flags & (1<<6))) {
panic("couldn't get memory map!");
}
/* Init mm */
mm_init((mmap_entry_t *) info->mmap_addr, info->mmap_length);
for(;;);
}
This is the output I get on qemu:
-- Scanning memory map --
Found segment starting from 0x0, with a length of 0
Found segment starting from 0x100000, with a length of 0
And yes, I am pushing eax and ebx before calling kmain. Any ideas on what is going wrong here?
It turns out that the bit masking stuff was the problem. If we drop that, we can still have 32-bit addresses and the memory map works just fine.

I have a problem reading ADC with DMA on STM32 F767zi. When I look into the buffer, all I see are zeros, and I do not know why?

The size of my buffer is 4096 and I want to fill the buffer with the adc values that are read.
#define ADC_BUF_LEN 4096
uint16_t adc_buf[ADC_BUF_LEN];
I am using this function to start the reading process of the ADC using DMA
HAL_ADC_Start_DMA(&hadc2, (uint32_t*)adc_buf, ADC_BUF_LEN);
Here are my configurations for the ADC
hadc2.Instance = ADC2;
hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV6;
hadc2.Init.Resolution = ADC_RESOLUTION_12B;
hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc2.Init.ContinuousConvMode = ENABLE;
hadc2.Init.DiscontinuousConvMode = DISABLE;
hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc2.Init.NbrOfConversion = 1;
hadc2.Init.DMAContinuousRequests = ENABLE;
hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
if (HAL_ADC_Init(&hadc2) != HAL_OK)
{
Error_Handler();
}
This my DMA configuration
/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA2_Stream2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
}
These are my interrupt functions. I set a toggle breakpoint on the first interrupt and when I debug, the LED does not turn on which suggests that the DMA isn't working?
/* USER CODE BEGIN 4 */
//Called when first half of buffer is filled
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc) {
//HAL_ADC_GetValue(&hadc2);
HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_SET);
}
//Called when buffer is completely filled
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){
HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET);
}
I set the prescaled to be divided by 6 if this information helps.
Please give me some advice!
Thank you in advance.

Store the ADC stream on µSD Card without loss on STM32H743ZI

I am working on a project in which I have to store the datas of an ADC Stream on a µSD card. However even if I use a 16 bits buffer, I lose data from the ADC stream. My ADC is used with DMA and I use FATFS (WITHOUT DMA) and the SDMMC1 peripheral to fill a .bin file with the datas.
Do you have an idea to avoid this loss ?
Here is my project : https://github.com/mathieuchene/STM32H743ZI
I use a nucleo-h743zi2 Board, CubeIDE, and CubeMx in their last version.
EDIT 1
I tried to implement Colin's solution, it's better but I have a strange things in the middle of my acquisition. However when I increase the maximal count value or try to debug, the HardFault_Handler appears. I modified main.c file by creating 2 blocks (uint16_t blockX[BUFFERLENGTH/2]) and 2 flags for when adcBuffer is half filled or completely filled.
I also changed the while(1) part in main function like this
if (flagHlfCplt){
//flagCplt=0;
res = f_write(&SDFile, block1, strlen((char*)block1), (void *)&byteswritten);
memcpy(block2, adcBuffer, BUFFERLENGTH/2);
flagHlfCplt = 0;
count++;
}
if (flagCplt){
//flagHlfCplt=0;
res = f_write(&SDFile, block2, strlen((char*)block2), (void *)&byteswritten);
memcpy(block1, adcBuffer[(BUFFERLENGTH/2)-1], BUFFERLENGTH/2);
flagCplt = 0;
count++;
}
if (count == 10){
f_close(&SDFile);
HAL_ADC_Stop_DMA(&hadc1);
while(1){
HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
HAL_Delay(1000);
}
}
}
EDIT 2
I modified my program. I set block 1 and block 2 with the length of BUFFERLENGTH and I added a pointer (*idx) to change the buffer which is filled. I don't have HardFault_Handler anymore but I still loose some datas from my adc's stream.
Here are the modification I made:
// my pointer and buffers
uint16_t block1[BUFFERLENGTH], block2[BUFFERLENGTH], *idx;
// init of pointer and adc start
idx=block1;
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)idx, BUFFERLENGTH);
// while(1) part
while (1)
{
if (flagCplt){
if (flagToChangeBuffer) {
idx=block1;
res = f_write(&SDFile, block2, strlen((char*)block2), (void *)&byteswritten);
flagCplt = 0;
flagToChangeBuffer=0;
count++;
}
else {
idx=block2;
res = f_write(&SDFile, block1, strlen((char*)block1), (void *)&byteswritten);
flagCplt = 0;
flagToChangeBuffer=1;
count++;
}
}
if (count == 150){
f_close(&SDFile);
HAL_ADC_Stop_DMA(&hadc1);
while(1){
HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
HAL_Delay(1000);
}
}
}
Does someone know how to solve my matter with these loss?
Best Regards
Mathieu

iPhone app kill process

I am basically looking to create Memory (RAM) optimization function as given in following applications. (For iPhone sdk)
https://itunes.apple.com/us/app/memory-100-pro/id644853504?mt=8
https://itunes.apple.com/th/app/memory-pro/id483447668?mt=8
This function basically kills third party app background process to achieve the same.
Can any one guide me that how can I find that particular process is not system process and kill the process.
I am using following code to get list of process with process id.
struct kinfo_proc *procs = NULL, *newprocs;
char thiscmd[MAXCOMLEN + 1];
pid_t thispid;
int mib[4];
size_t miblen;
int i, st, nprocs;
size_t size;
size = 0;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_ALL;
mib[3] = 0;
miblen = 3;
st = sysctl(mib, miblen, NULL, &size, NULL, 0);
do {
size += size / 10;
newprocs = realloc(procs, size);
if (newprocs == 0) {
if (procs)
free(procs);
errx(1, "could not reallocate memory");
}
procs = newprocs;
st = sysctl(mib, miblen, procs, &size, NULL, 0);
} while (st == -1 && errno == ENOMEM);
nprocs = size / sizeof(struct kinfo_proc);
/* Now print out the data */
for (i = 0; i < nprocs; i++) {
thispid = procs[i].kp_proc.p_pid;
strncpy(thiscmd, procs[i].kp_proc.p_comm, MAXCOMLEN);
thiscmd[MAXCOMLEN] = '\0';
printf("%d\t%s\n", thispid, thiscmd);
NSString * processName = [[NSString alloc] initWithFormat:#"%s", procs[i].kp_proc.p_comm];
if([processName isEqualToString:#"templerunbrave"])
kill(thispid, SIGKILL);
}
/* Clean up */
free(procs);
A 3rd party app is sandboxed and does not have the power or authority to arbitrarily kill processes and threads that do not belong to it.
The way these "memory" apps work is by manually allocating memory incrementally in a for loop until they get memory warnings, then manually freeing the memory. Because the OS does not know that your memory is not being used in the app, it takes active memory away from other apps, sometimes even force closing them in order to provide their memory resources to your app. Once you manually free the memory, this memory that was allocated to your app is now available to the whole system, but the other apps which were killed or in deep sleep will remain killed or in deep sleep.

AudioBufferList Increase in Memory Usage

I have the following code in a loop (it gets called every 1/4 second).
(I have removed the rest of the code to narrow the problem down to the following).
dispatch_async(self.audioQueue, ^{
AudioBufferList *aacBufferList;
aacBufferList = malloc(sizeof(AudioBufferList));
aacBufferList->mNumberBuffers = 1;
aacBufferList->mBuffers[0].mNumberChannels = aacStreamFormat.mChannelsPerFrame;
aacBufferList->mBuffers[0].mDataByteSize = maxOutputPacketSize;
aacBufferList->mBuffers[0].mData = (void *)(calloc(maxOutputPacketSize, 1));
// Other code was here. As stated above, I have removed it to isolate the problem to the allocating and freeing of memory for the AudioBufferList
freeABL(aacBufferList);
}
And the freeABL function:
void freeABL(AudioBufferList *abl)
{
for (int i = 0; i < abl->mNumberBuffers; i++)
{
free(abl->mBuffers[i].mData);
abl->mBuffers[i].mData = NULL;
}
free(abl);
abl = NULL;
}
The problem I have, is every time this loops the memory consumption of my app increased, until I receive a memory warning.

Resources