I try to make LPC3250 to boot from a built-in-FPGA RAM in the way of EMC BOOT. It's to say, I made a SRAM by using of FPGA, then connect the SRAM to LPC3250's EMC controller, the first address is 0xE0000000 by the way. Then I put "0x13579BD2" to the first word of the SRAM, and the code to the rest.
I write the code in asm. It implement a simple function to light a led, following is the code. Suppose AA is the base address of the gpio's register associate with that led, and BB is the value of the register.
main MOV R0, AA
MOV R1, BB
MOV R2, #1
loop SUB R2, R2, #1
CMP R2, #0
BNE loop
STR R1, [R0, #4]
B main
The problem is, every time I add the "loop" code to the little program, the led won't be on, and the program just loop in the loop all the time although it should not loop. But if I comment the "loop" code or delete that part, the led can be light on. It means that LPC3250 do can execute some instructions corrcetly, some not, which is the jump instruction "B". I've take some other experiments, and I find that if I want the PC pointer jump backward 56 steps, it turns out that it just jump 20 steps.
I cannot figure out why this happened. Please help me.
Solved! Go to Solution.
Today, I'm gonna to end this question.
Finally, I figure out what the true cause is. It's because the address's meaning is not consistent between the FPGA-SRAM and the LPC3250. I should have noticed this ealier.
Well, let me explain the whole thing in detail. At the beginning, I just want to make LPC3250 boot from a FPGA-SRAM like booting from a norflash. So I make a block of SRAM in FPGA, whose data width is 32bits, depth is 4096, and the address bus is 11bits-wide with each address points to a 32bits-word. I place "0x13579BD2" in the first word of the SRAM to tell the LPC3250 this is a 32bits device. I thought that the address came from the EMC was byte addressing, so I omitted the low 2 bits when I was connecting the address bus among SRAM and EMC. Actually, it's word addressing, I should not omit the low 2 bits. I think it might be "0x13579BD2" make the core to configure the EMC to do so.
That's it.
Today, I'm gonna to end this question.
Finally, I figure out what the true cause is. It's because the address's meaning is not consistent between the FPGA-SRAM and the LPC3250. I should have noticed this ealier.
Well, let me explain the whole thing in detail. At the beginning, I just want to make LPC3250 boot from a FPGA-SRAM like booting from a norflash. So I make a block of SRAM in FPGA, whose data width is 32bits, depth is 4096, and the address bus is 11bits-wide with each address points to a 32bits-word. I place "0x13579BD2" in the first word of the SRAM to tell the LPC3250 this is a 32bits device. I thought that the address came from the EMC was byte addressing, so I omitted the low 2 bits when I was connecting the address bus among SRAM and EMC. Actually, it's word addressing, I should not omit the low 2 bits. I think it might be "0x13579BD2" make the core to configure the EMC to do so.
That's it.
Hi,
I'm glad yo hear that your issue was solved. Thanks for sharing your solution with the Community!
Best regards!
/Carlos
Hi,
In this case, it seems that there are two things that could be changed in order to ensure the proper functionality of your test application.
The first one consists on the loop, which according with the ASM instructions, it decrements the R2 until zero for getting out of the “loop” and continuing the execution until the branch to the main, isn’t it? However, the “SUB” instruction has a missing operand, as the correct usage includes 3 operands (destination, source1, source2); seems it should be “SUB R2, R2, #1” (to decrement 1 from R2, and store the result on R2). This seems to be the cause why the application is blocked on the loop, and also may be the cause of the incorrect PC modifications, if the compiler “optimizes” the incorrect instruction, skipping it.
The second factor consists on using a reliable RAM, in order to verify that the memory will not be the issue, ensuring first that the code is right, and then testing the correct code on the implemented RAM.
Hope this will be useful for you.
Best regards!
/Carlos
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
I've made a big progress. There is nothing wrong with the code and the FPGA ram, it's because the ARM core uses a weird addressing mode when executes the B instruction. Take the code above as an example:
After compiling, the machine code of instruction "BNE loop" should be "1AFFFFFC" , which will make the PC pointer jump backwards 4 32bit-Words or 16 bytes, according to ARM assembly convention. And IAR assembler agrees with that. "1AFFFFFC" works fine when debugging. But if I put the code to the FPGA ram and make the LPC3250 to boot from EMC, problem appear. Based on what the ARM assembly manual says, the address jumped to is calculated in this formula, PC + offset * 4, or current code address + 8 + offset * 4, and the offset here is "FFFFFC". In order to find out what's actually wrong with my code, I wrote another program to do experiment. The program is:
main NOP
NOP
...
...
NOP
NOP
B main
then I find out that if I want the PC jumps to the right place, I should modify the B instruction's machine code's offset value. And there is a pattern to get the new offset value. It's offset_new = offset_old * 4 + 6(or 7, or 8, or 9), then use the low 24 bits of the offset_new to replace offset_old, which is "FFFFFC" in my example. So I should change "1AFFFFFC" to "1AFFFFF6" to get the PC to the right place. This is weird, because there is no guides said anything about this kind of situation.
Wondering if you know anything about this problem.
Hi,
Sometimes, the NOP is not necessarily a time-consuming instruction, rather, it may be used for instructions alignment. Please take a look at the following thread:
https://community.nxp.com/thread/387290
Hope this will be useful for you.
Best regards!
/Carlos
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Well, thanks for letting me konw "NOP" has another meaning. But I don't think I have to worry about NOP being ignored by the processor, because NOP is a pseudo assembler instruction, which will be replaced by "MOV R0, R0" after compiling.
Besides, I'm not using NOP to consume time what it actually can be used to, I'm using it as a easy way to find out how B instruction is executed.
Anyway, thank you very much!
I really appreciate your response. I have been bothered by this problem for about 2 months, finally I get somebody to talk to.
Well, about your first suggestion, it's my bad. The time I post the question was too late in my day, and I mind was not very clear at that time, so I made some mistakes when typing my confusion. I mean the code "SUB R2, R2, #1" is a typing mistake. Then the second suggestion, I have used IAR to debug the little program via Jlink, and it works right. I think it can prove that in a reliable RAM like you said the program can run properly. But I'll check that again anyway. I'll update soon.
Besides the two possible problems you have posted, is there other potential problems in my situation? I used to think it might be because of some bit of the Data Bus keeping '0' or '1', but this cannot explain why only the jump instruction is executed wrong.