|
241
|
Using Arduino / Programming Questions / Re: Can you get at the return address from a C function?
|
on: March 05, 2012, 02:39:01 pm
|
This reminded me of a piece of code I wrote a few months ago. I wanted to write a function: boolean every(long micros) , that would return true if micros microseconds had elapsed since last time it returned true, and false at all other times. So you could write for example: if(every(1000000))toggleLed(13); To discriminate between different calls to every in the same program I needed to know the return address to the caller, and I used __builtin_return_address(0) for that. There is __builtin_frame_address too which might be helpful. Here are the docs for those functions: http://gcc.gnu.org/onlinedocs/gcc/Return-Address.html(What I ended up doing with every was to use preprocessor metaprogramming to make every into a macro. Then I could use __COUNTER__ to discriminate between calls. Usage is now even simpler: every(1000000)toggleLed(13); This is probably the worst hack I have ever written, but for simple LED flashing it seems to work) //usage: every(time) doSomething(); // time = period in microseconds // Be careful, this macro has a trailing if and can bite you. You have been warned! // This code guaranteed safe for use in life support systems, nuclear power stations // and large hadron colliders
#define CONCAT( a, b ) a##b #define every2(id,time) static unsigned long CONCAT(_ec , id) = 0; \ unsigned long CONCAT(_et , id) = micros(); \ boolean CONCAT(_eb , id) = (CONCAT(_et , id) -CONCAT(_ec , id)) >= time; \ if(CONCAT(_eb , id)) CONCAT(_ec , id) += time; \ if(CONCAT(_eb , id)) #define every(time) every2( __COUNTER__ ,time)
boolean p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13;
void setup() { for(int i=2;i<=13;i++)pinMode(i,OUTPUT); }
void loop() { every(30000000/51) digitalWrite( 2, p2= !p2); every(30000000/52) digitalWrite( 3, p3= !p3); every(30000000/53) digitalWrite( 4, p4= !p4); every(30000000/54) digitalWrite( 5, p5= !p5); every(30000000/55) digitalWrite( 6, p6= !p6); every(30000000/56) digitalWrite( 7, p7= !p7); every(30000000/57) digitalWrite( 8, p8= !p8); every(30000000/58) digitalWrite( 9, p9= !p9); every(30000000/59) digitalWrite(10,p10=!p10); every(30000000/60) digitalWrite(11,p11=!p11); every(30000000/61) digitalWrite(12,p12=!p12); every(30000000/62) digitalWrite(13,p13=!p13); }
|
|
|
|
|
242
|
Using Arduino / Storage / Re: memory addressing
|
on: February 29, 2012, 02:26:36 pm
|
Thank you for your reply Try every address in the 32-bit address space. U4 and U5 must be in there somewhere. Do you mean I should use 2 32 addresses? Yes, try every address there is. There must be some addresses where U4 and U5 are. Also, try to find the highest addresses for U2 and U3. Then you might find addresses for U4 and U5 after that. If it is DDR it could happen for example that U2 has addresses 4 and 12, but address 4 gets written very very quickly before address 12 and you didn't see it (it would be there for less than half a clock). Do you mean that it writes to different modules for the same address? No, it writes to the same module for two different addresses, but it writes the first one so quickly that you won't see it unless you have a very fast logic analyser. That might be why you can't find address 16.
|
|
|
|
|
243
|
Using Arduino / Storage / Re: memory addressing
|
on: February 29, 2012, 08:05:29 am
|
|
Try every address in the 32-bit address space. U4 and U5 must be in there somewhere.
Do you know if the ram is single data rate or double data rate? If it is DDR it could happen for example that U2 has addresses 4 and 12, but address 4 gets written very very quickly before address 12 and you didn't see it (it would be there for less than half a clock).
The clocks to U3 and U5 could be the same as U2 and U4 but buffered (it's not good to have one clock signal driving too many things without buffers). Or it could be 90 degrees out of phase, so that the CPU can write to U3 then write to U2 a quarter of a clock later (and if it is DDR, it could write to U3 again after half a clock then U2 after 3/4 of clock)
|
|
|
|
|
244
|
Using Arduino / Storage / Re: memory addressing
|
on: February 28, 2012, 04:16:26 pm
|
|
Can you post the code you use for the memory testing? Is it running on the same computer, or is it on another machine and using JTAG?
If it was running on the same computer and the cpu has an MMU, it might be doing address translation. If you allocate memory on Linux it doesn't map it to physical memory until you write to it. If you allocate a big piece of memory and just write to the end of it, LInux might remap that piece to the beginning of physical memory. To get around this, write 0 to every address in your memory allocation before you do anything else.
Some embedded linux systems have a command called devmem or devmem2 which bypasses address translation and writes directly to physical memory locations. If you use it you have to be very very careful because if you accidentally write to an address that Linux is using it will crash. JTAG should also bypass the address translation I think (but I've never used it so I don't know for sure)
Did you try the same thing with U5?
|
|
|
|
|
245
|
Using Arduino / Storage / Re: memory addressing
|
on: February 23, 2012, 05:21:45 pm
|
"Interleaving" is just the proper term for your second example. So when you wrote: 1st address in module 1 2nd address in module 2 3rd address in module 3 4th address in module 4 5th address in module 1 6th address in module 2 7th address in module 3 8th address in module 4 .. .. the last but one address in module 3 the last address in module 4 The correct term for this is "interleaved memory". For your first example: 1st address in module 1 2nd address in module 1 3rd address in module 1 4th address in module 1 5th address in module 1 6th address in module 1 7th address in module 1 8th address in module 1 ... ... the last but one address in module 4 the last address in module 4 that is called "non-interleaved memory" What I meant in my first post was that there are other kinds of interleaved memory. The most common way is this: 1st address in module 1 2nd address in module 2 3rd address in module 1 4th address in module 2 5th address in module 1 6th address in module 2 7th address in module 1 8th address in module 2 ... ... the last but one address in module 3 the last address in module 4
|
|
|
|
|
246
|
Using Arduino / Storage / Re: memory addressing
|
on: February 23, 2012, 02:05:37 pm
|
|
Unfortunately it is very complicated - I once tried to make a ram interface (using an FPGA), I never want to do that again!
It's hard to think of a way you might be able work out easily which module is at which address. Do you have any test gear (oscilloscope, logic probe) you can connect up to the boards while they are running? If you do, try connecting it to CS on one of the modules and see if there is more activity on the CS line when your memory test is running at certain parts of the address space. Or by connecting to one of the data lines and using some specific data sequences (say 0xffff0000 0xffff0000 oxffff0000 .... and 0xffffffff 0x00000000 0xffffffff 0x00000000) you might be able to work out if data is interleaved.
If you don't have test gear you might need to think of a way to cause a temporary fault in a module so your memory test can detect it. I can't think of a good reliable way to do this. It would help if you had a module you knew to be faulty, then you could just do a memory test, move the bad module around, and observe how the faulty address changed.
The CPU can complicate things further if it has cache and/or an MMU. With cache, writes and reads won't happen immediately but will be queued up and blocks of memory will be written and read in one go. With an MMU any memory address can be remapped anywhere else so there's no knowing what chip an address will end up on.
|
|
|
|
|
247
|
Using Arduino / Storage / Re: memory addressing
|
on: February 23, 2012, 08:38:25 am
|
|
Remember that there is RAS and CAS too - the address bus is used to select a row address and a column address, so there could be anything up to 26 bits of address from the 13 bit address bus. To know how many column bits and row bits there are you need to read the data sheet for the ram modules.
I think bank selects should normally be MSBs (but I saw one design where they were LSBs)
As for interleaving, 12121212.....34343434 and 11221122....33443344 are also possibilities. Are you able to remove the modules? If so, do a memory bandwith test with 1 module installed and 2 modules installed - if it goes faster, it is interleaving memory addresses.
|
|
|
|
|
249
|
Using Arduino / Programming Questions / Re: How to give a C++ variable name to an asm statement?
|
on: February 07, 2012, 09:53:17 pm
|
|
Are you sure you know what you're doing? I *think* it's m not M but I am not sure. With inline asm the best technique is to search Google for as many examples as you can find of other people using it as it is not very well documented, the only way is to find someone elses example that works and copy it. Then disassemble the elf file and make sure it looks like it has done what you expect!
|
|
|
|
|
250
|
Using Arduino / Programming Questions / Re: Mixing C with Assembler: Assembly code before push instructions in a function
|
on: February 07, 2012, 12:14:05 pm
|
Register r0 may be freely used by your assembler code and need not be restored at the end of your code. It's a good idea to use __tmp_reg__ and __zero_reg__ instead of r0 or r1, just in case a new compiler version changes the register usage definitions.
So I believe I can safely use r0. All I need is to use the in instruction, then save that register to RAM, and I should be good to go. No, you are in an ISR. The main code might be using r0 temporarily when your ISR gets called - if you touch r0, you mess up the main code. I once tried doing a similar thing with r1, thinking that because it should always be 0 I could quickly use it in an ISR and zero it again afterward - and it didn't work either. Turns out the zero register wasn't always zero!
|
|
|
|
|
252
|
Using Arduino / Programming Questions / Re: Math.h
|
on: February 01, 2012, 09:39:17 pm
|
|
Also the sin and cos functions work in radians, not degrees (and atan2 returns its result in radians).
To convert from radians to degrees, divide by 180.0 and multiply by PI
|
|
|
|
|
253
|
Using Arduino / Displays / Re: TVout hardware and voltages.
|
on: February 01, 2012, 09:23:20 pm
|
|
The video-in socket on your TV has (or should have) a 75 ohm input impedance, which will drop the voltage to 1V.
Try measuring the resistance of the video-in on your TV, if it reads 75 ohms it's safe to plug it in. If it is much higher you need a 75 ohm resistor in parallel with the socket.
|
|
|
|
|
254
|
Using Arduino / Project Guidance / Re: 3d printer using arduino uno
|
on: January 27, 2012, 12:05:12 pm
|
|
I have a reprap controlled by a Duemilanove. It is enough to control 3 axes, end stops, the extruder and hot end, heated bed and a fan, however I have now run out of pins so can't add anything else (LCD or 2nd extruder for example).
There's easily enough memory, my firmware takes about 16k, the limitation is the number of pins. I'd recommend using a Mega and one of the more common electronic kits, as repraps can be very hard to set up and it's a lot easier to get help if your build is closer to the norm.
|
|
|
|
|