printf() make the code work
Hi, all
I am in a trouble with printf(...). The problem is , when I insert the printf(...), my code runs correctly, when I ignore printf(...), it will fail.
The simple code runs in NIOS II, for co-operating image processing. Part of main() shown as below:
int main()
{
printf("Hello from Nios II!\n");
/*variable declaration*/
alt_u32 proc_num = 0;
alt_u32 frame_len = 0;
alt_u32 read_addr[16];
alt_u32 write_addr[16];
alt_msgdma_standard_descriptor a_descriptor[16]; //maximum 16 descriptors
alt_msgdma_dev * msgdma_dev_ptr = alt_msgdma_open("/dev/msgdma_img_proc_csr");
if (!msgdma_dev_ptr){
printf ("FAIL: Unable to open msgdma device");
return 1;
}
alt_msgdma_register_callback(msgdma_dev_ptr, msgdma_callback_function, 0, msgdma_dev_ptr);
/*fill in address array*/
for (int i = 0; i < 16; ++i){
read_addr[i] = RAM_BASE_ADDRESS + i * (0x800000);//start at 0, 16M, 32M...
write_addr[i] = RAM_BASE_ADDRESS + ( i + 1) * (0x800000); //start at 8M, 24M, 40M...
//printf("read address %d is 0x%08x\n", i, (unsigned int)read_addr[i]);
//printf("write address %d is 0x%08x\n", i, (unsigned int)write_addr[i]);
}
alt_dcache_flush_all(); // need to make sure all the data is written out to memory
do {
printf("spin until mailbox int.\n");
while (mb_interrupt_fired == 0) {} //wait for mailbox int
mb_interrupt_fired = 0; //restore int flag
/*prepare for 1st process*/
//calc frame length
proc_num = 0;
frame_len = ((IORD_32DIRECT(IMG_PROC_SUBMOD_0_BASE, IMG_SIZE_OFS) & VSIZE_MASK )>> 16) * \
(IORD_32DIRECT(IMG_PROC_SUBMOD_0_BASE, IMG_SIZE_OFS) & HSIZE_MASK );
proc_num = IORD_32DIRECT(IMG_PROC_SUBMOD_0_BASE, IMG_PRE_PROC_CH_EN_OFS);
printf("proc channel enable register is 0x%08x.\n", (unsigned int)proc_num);
proc_num = 0;
for (int i = 0; i < 32; ++i){
proc_num = proc_num + ((IORD_32DIRECT(IMG_PROC_SUBMOD_0_BASE, IMG_PRE_PROC_CH_EN_OFS) >> i) & 0x1);
}
printf("Number of proc loops is %d.\n", (int)proc_num);
/****************generate descriptor start***************/
//generate control bit
unsigned long control_bits = ALTERA_MSGDMA_DESCRIPTOR_CONTROL_TRANSFER_COMPLETE_IRQ_MASK | ALTERA_MSGDMA_DESCRIPTOR_CONTROL_ERROR_IRQ_MASK;
//generate descriptors
for (int i = 0; i < proc_num; ++i) {
if (alt_msgdma_construct_standard_mm_to_mm_descriptor (msgdma_dev_ptr, a_descriptor + i, (alt_u32 *)read_addr[i], (alt_u32 *)write_addr[i], frame_len, control_bits)!=0) {
printf("Failed to construct descriptor.");
return 1;
}
}
//write descriptor to msgdma
while ((IORD_ALTERA_MSGDMA_CSR_STATUS(MSGDMA_IMG_PROC_CSR_BASE) & ALTERA_MSGDMA_CSR_RESPONSE_BUFFER_FULL_MASK) != 0) {}
if(alt_msgdma_standard_descriptor_async_transfer (msgdma_dev_ptr, a_descriptor) != 0)
{
printf("Failed to write descriptor0 to the descriptor SGDMA port.");
return 1;
}
printf("Now waiting for interrupt... \n");
while (msgdma_interrupt_fired == 0) {} // wait for msgdma int
//printf("msgdma_int is %d\n",msgdma_interrupt_fired );
msgdma_interrupt_fired = 0;
//switch proc channel
alt_u32 temp_data = IORD_32DIRECT(IMG_PROC_SUBMOD_0_BASE, IMG_PRE_PROC_CH_EN_OFS) & (0xfffffffe);
IOWR_32DIRECT(IMG_PROC_SUBMOD_0_BASE, IMG_PRE_PROC_CH_EN_OFS, temp_data);
//handle next proc loops
if (proc_num > 1){
for (int i = 1; i < proc_num; ++i){
/****************generate descriptor start***************/
//wait until buffer has space
while ((IORD_ALTERA_MSGDMA_CSR_STATUS(MSGDMA_IMG_PROC_CSR_BASE) & ALTERA_MSGDMA_CSR_RESPONSE_BUFFER_FULL_MASK) != 0) {}
/****************generate descriptor end****************/
//printf("the descriptor read address is 0x%08x\n", (unsigned int)(a_descriptor[i].read_address));
//printf("the descriptor write address is 0x%08x\n", (unsigned int)(a_descriptor[i].write_address));
//printf("the descriptor transfer length is 0x%08x\n", (unsigned int)(a_descriptor[i].transfer_length));
//printf("the descriptor control register is 0x%08x\n", (unsigned int)(a_descriptor[i].control));
//write descriptor to msgdma
if (alt_msgdma_standard_descriptor_async_transfer (msgdma_dev_ptr, a_descriptor + i ) != 0)
{
printf("Failed to write descriptor %d to the descriptor SGDMA port.\n", i);
return 1;
}
//switch proc channel
while (msgdma_interrupt_fired == 0) {} // wait for msgdma int
msgdma_interrupt_fired = 0;
temp_data = IORD_32DIRECT(IMG_PROC_SUBMOD_0_BASE, IMG_PRE_PROC_CH_EN_OFS) & (0xfffffffe<<i);
//printf("The CH_EN register is 0x%08x.\n",temp_data);
IOWR_32DIRECT(IMG_PROC_SUBMOD_0_BASE, IMG_PRE_PROC_CH_EN_OFS, temp_data);
}
}
//after last proc loop, write PCIE-CRA to generate interrupt
IOWR_32DIRECT(PCIE_CV_HIP_AVMM_0_BASE+A2P_MAILBOX0_OFS, 0, 0x1);
} while (1);
return 0;
}
That is if only the printf() (coloured in blue) runs before the alt_msgdma_standard_descriptor_async_transfer (), then the MSGDMA can run correctly, otherwise, it will hang on. When I use sigtap to cpature the descriptor write bus, the regions of descriptor is all 0. I have tried to do following experiments:
Add delay instead of printf(), but not work.
Print some others not related with descriptor, such as "print("Hello!\n")", also does not work.
Also I have tried to add volatile , static keywords before the a_desciptor[] array, no use.
Only enable one of the four blue "printf()", it works.
Set a breakpoint at the "if" sentence after printf, and run by manually click "RESUME" button for each loop, it also works.
I am so confused about this , Appreciate to any suggestion.