Why is it that if we change setup for strobe for EMIF-ASYNCH1/2/3 output memory access, we never get a strobe of anything other than 26us?
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi Anthony, thank you for the quick response.
I have to forward some of your questions to the EE. I worked with him over the weekend, so I have some of the answers, but he did the actual measurements. I was just behind the computer.
Our task was to test out the discrete out signals, what he called parallel 4xxx interface. We have 8 signals going out and 8 coming in, however we wanted to test the discrete out signals. The EE had me alternate 0x00 and 0xFF on the discrete lines every 50ms. I set up a 50ms timer and wiggled the discrete out signals.
Here is the code:
#define lpbyDiscreteIn (uint8 *)0x60000000 #define lpbyDiscreteOut (uint8 *)0x64000000 static uint8 isDiscreteLow = FALSE; // SMW DEBUG -- void rtiNotification(uint32 notification) { /* enter user code between the USER CODE BEGIN and USER CODE END. */ /* USER CODE BEGIN (9) */ if (rtiNOTIFICATION_COMPARE0 == notification) { // Test: Discrete Out uint8 uValue2 = 0; uValue2 = (FALSE == isDiscreteLow ? 0x00 : 0xFF); isDiscreteLow = !isDiscreteLow; *lpbyDiscreteOut = uValue2; } else if (rtiNOTIFICATION_COMPARE1 == notification) { } /* USER CODE END */ }
The EE tested the signals, however what he saw was 26us on any of the pins with a random other timing element on the oscilloscope. He had me change the values from the default to (2, 5, 3, 2, 5, 3, 1), however that had no effect on the timing that we saw.
Also, is there a nice HalCoGen #define, method, or whatnot to write and read from the discrete out lines rather than the crude #define that I used with lpbyDiscreteIn and lpbyDiscreteOut?
Hi Anthony, we now get 5 pulses instead of one on the writes only and they are approximately 800ns wide. The reads are correct. ASYNCH1 is read and ASYNCH2 is write. We tried for sheer testing purpose to make through code ASYNCH1 write and the problem, namely the 5 pulses, traveled with the write.
Here are the addresses to which read and write.
#define lpbyDiscreteIn (uint8 *)0x60000000 #define lpbyDiscreteOut (uint8 *)0x64000000
Here is my test code that I have in a 100ms timer interrupt.
// Test: Discrete In if (10 <= uDiscreteIn) { uint8 uValueIn = *lpbyDiscreteIn; char szValueIn[12]; char szLine[81]; *szLine = 0; itoa(uValueIn, szValueIn); strcat(szLine, "Discrete In = "); strcat(szLine, szValueIn); strcat(szLine, "\r\n"); fifoenter(szLine); uDiscreteIn = 0; } else uDiscreteIn++; // Test: Discrete Out if (10 <= uDiscreteOut) { // uint8 uValue2 = 0; // uValue2 = (FALSE == isDiscreteLow ? 0x00 : 0xFF); // isDiscreteLow = !isDiscreteLow; // *lpbyDiscreteOut = uValue2; *lpbyDiscreteOut = (uint8)uDiscreteValue; if (255 < ++uDiscreteValue) uDiscreteValue = 0; uDiscreteOut = 0; // static int iBit = 0; // uint8 uValue = 1 << iBit; // *lpbyDiscreteOut = uValue; // iBit++; // if (8 <= iBit) // iBit = 0; } else uDiscreteOut++;
What we see on the scope are 5 pulses on the write side. When I read data back, we see 223, although upon startup the value builds up to that, so it might be 14, then 20, then 48, then 223, where it settles. The EE says that he only sees 5-pulses but was expecting one (1).
Here are the ASYNCH1 and 2 configuration screenshots. We tried different settings, even putting 1 for the write and read strobe values, but that did not help our problem.
I have a tested straight through 26-pin ribbon cable connected the in to the out. I increment data from 0 to 255 and then repeat out on the discrete port and read the values back, as seen in the code above. What I see is merely 223 and 5 pulses on the scope with the EE expecting to see 1 pulse.
Hi Anthony,
(from the EE)
1. We are measuring at nCS3.
2. By 5-pulses, I mean 5 times nCS3 goes low with the low time being 600ns and the high time being 700ns.
3. That is correct and it is a data bus value, which we read and is in decimal.
Thanks,
Sarah
Hi Sarah,
If they are distinct pulses - then we should understand the data type for your variables lpbyDiscreteOut , lpbyDiscreteIn.
Says they are uint8 *, so you should be seeing an assembly instruction 'LDRB' for the read and 'STRB' for the write.
If you can confirm that the assembly code being executed is an LDRB and an STRB (open disassembly window / use 'green' assembly step arrows' in ccs... then maybe the next step is to check your MPU settings. If the EMIF is setup for 'Normal' type then it may be that something funny is going on with the CPU. I can't put my finger on it, but there's write buffering and the CPU probably reads ahead too when the memory is type 'Normal' so you want to make sure it' strongly ordered.
You are trying to implement an IEEE-488 interface (AKA GPIB or HPIB)? Or something else?
Thanks and Best Regards,
Anthony
EDIT: PS forgot to ask you EMIF clock frequency - in case there is a question about the strobe timing itself.. Was focused on the # of pulses but need to know the EMIF clock to confirm that the width is correct.
Hi Anthony,
Here is the disassembly, which as you can see does use the LDRB for the read and STRB for the write.
182 uint8 uValueIn = *lpbyDiscreteIn; 0003aeb0: E3A0C206 mov r12, #0x60000000 0003aeb4: E5DCC000 ldrb r12, [r12] 0003aeb8: E5CDC004 strb r12, [sp, #4] 203 *lpbyDiscreteOut = (uint8)uDiscreteValue; 0003af2c: E59FC790 ldr r12, [pc, #0x790] 0003af30: E3A00319 mov r0, #0x64000000 0003af34: E5DCC000 ldrb r12, [r12] 0003af38: E5C0C000 strb r12, [r0]
We did not use the MPU, as we disabled that, but we enabled the MPU, as shown below, to no change, still the 5-pulses. The applicable region is 5, because the address range is 0x60000000 through 0x67FFFFFF.
Did you want another set of values on this tab?
>> You are trying to implement an IEEE-488 interface (AKA GPIB or HPIB)? Or something else?
We are outputting 8 parallel values and reading the same 8 parallel values back after looping them back via RS-422 8-bit parallel link.
>> PS forgot to ask you EMIF clock frequency - in case there is a question about the strobe timing itself.. Was focused on the # of pulses but need to know the EMIF clock to confirm that the width is correct.
10 MHz
Thanks,
Sarah
Yes, I like the _mpuInit_() comment too, as I did not know that I have to call that, however in stepping through the debugger or just uploading code, code execution stops right at the _mpuInit_() call.
void doInitDiscrete() { // Initialize ASYNC1, 0x60000000, for discrete intput with order the same as old CCM; method ReadDiscrete(). emif_ASYNC1Init(); // Initialize ASYNC2, 0x64000000, for discrete output with order the same as old CCM; method WriteDiscrete(). emif_ASYNC2Init(); // Enable the MPU unit to avoid extra writes. _mpuInit_(); }
I call this function just before the "_enable_IRQ();" call.
I only enabled the EEPROM stuff and those settings look okay.
Why could the reason that I get hung up on that call be and how do I fix the problem?
The _mpuInit_ function writes to MPU co-processor registers which require the CPU to be in an "privilege state". If the CPU is in user (USR) mode the _mpuInit_ function will generate an abort.Why could the reason that I get hung up on that call be and how do I fix the problem?
Prior to stepping over the _mpuInit_ function can you check in the CCS Target Status view what is the state of the CortexR4 CPU. In the following, albeit for a different CPU to yours, the information of interest is the "Status mode":
If you tried running in privileged mode like Chester suggested and still having issues, take a look at this app note infocenter.arm.com/.../index.jsp .
This section is taken from AN296 at ARM info center : "None of the regions are defined or enabled after reset. Any access which lies outside a defined and enabled region when the MPU is enabled will cause an abort. Therefore, at least one region must be defined before enabling the MPU after reset. If the MPU is enabled and no regions are defined, the processor enters a state from which it is recoverable only by a further reset"
So, any memory that you access (R/W/X) should be defined and enabled before you enable mpu.
I believe HalCogen has a set of predefined regions with the correct settings by default for FLASH/RAM/Peripherals. You can enable all those regions plus the specialized region for EMIF.
Thank you for the information. From looking at the screen shot of the MPU settings for regions 1 to 5 which Sarah posted shows that only region 5 which is for the EMIF is enabled. The MPU for regions 2 (flash) and 3 (RAM) are not enabled.Joe Josn said:This section is taken from AN296 at ARM info center : "None of the regions are defined or enabled after reset. Any access which lies outside a defined and enabled region when the MPU is enabled will cause an abort. Therefore, at least one region must be defined before enabling the MPU after reset. If the MPU is enabled and no regions are defined, the processor enters a state from which it is recoverable only by a further reset"So, any memory that you access (R/W/X) should be defined and enabled before you enable mpu.
Since HALCoGen leaves the CPU in system mode by default, I believe the problem is caused by disabling MPU access to FLASH/RAM/Peripherals.
Yes, that means you are in privileged mode. i.e. the CortexR4 mode isn't the problem.Sarah Weinberger said:Does that mean that I am in privileged mode?
I be the first person to say that I do not know what each Halcogen/Hercules region means or which ones I should enable or to what value.
What does OINC mean?
I enabled region 2 and 3, as shown as follows, and was able to go a couple steps beyond the _mpu_Init(), however I still halt, just a bit later, so that is the area to make a positive change.
What further changes do I need to make?
I think the problem is that the region(s) for the peripherals are still disabled, which will then cause an abort when the CPU attempts to access peripheral accesses.Sarah Weinberger said:I enabled region 2 and 3, as shown as follows, and was able to go a couple steps beyond the _mpu_Init(), however I still halt, just a bit later, so that is the area to make a positive change.What further changes do I need to make?
I agree with Anthony's suggestion of starting by copying the MPU settings from a clean HALCoGen project.
I am not sure what type should be set to for the EMIF Region 5 to solve your original problem, but suggest repeat your tests with the default MPU settings and the MPU enabled (via the call to _mpuInit_).
Hi Chester/Anthony,
I did create a clean Halcogen project and set the R4-MPU-PMU configuration to that of a clean project. That resolved the _mpu_Init_() issue and allowed my project to run with MPU enabled. Thanks!
I then played with the 5 Region Types for Region 5 (my discrete in/out signals), as described earlier. One gave me 223 as a value read in, while the others gave me a sort of number increment, just not what I expected. The EE is not here today, will be on Saturday, so I cannot comment on the number of strobes. I can, however, on the values.
I created multiple columns, just so there is not a hugely double columns. If working properly, the value that I write out should be identical to what I read in.
Here is the region type that goes along with that.
Note: The tool-tip does not correspond to the actual values.
Here is the code that I have executing in a 100ms timer.
// Test: Discrete In if (10 <= uDiscrete) { // Write out the value. *lpbyDiscreteOut = uDiscreteValue++; // Read the discrete value back in. uint8 uValueIn = *lpbyDiscreteIn; // Display the discrete value. char szValueIn[12]; char szLine[81]; strcpy(szLine, "Discrete: Read = "); itoa(uValueIn, szValueIn); strcat(szLine, szValueIn); strcat(szLine, ", Should Be = "); itoa(uDiscreteValue, szValueIn); strcat(szLine, szValueIn); strcat(szLine, "\r\n"); fifoenter(szLine); // Rinse and repeat. uDiscrete = 0; } else uDiscrete++;
I allocated the value, uDiscrete, as a static at the top of the source file.
#define lpbyDiscreteIn (uint8 *)0x60000000 #define lpbyDiscreteOut (uint8 *)0x64000000
0 reads in as 223, 1 reads in as 0, 2 reads in as 17, then consistent until 16 reads in as 31, but then 17 reads in as 0. I had a gap, only because I started capturing not at zero and my scroll history was not set high enough for 18 through 72. Anyways, the pattern is that the numbers consistently increment, but then drop down or rise up (194 reads in as 209).
What setting or lack thereof causes the read to not equal the write, considering that I do one right after the other?
I think one issue is caused by the following test code which increments the uDiscreteValue variable after performing the write but before reporting the "Should Be" valur:Sarah Weinberger said:What setting or lack thereof causes the read to not equal the write, considering that I do one right after the other?
// Write out the value. *lpbyDiscreteOut = uDiscreteValue++; // Read the discrete value back in. uint8 uValueIn = *lpbyDiscreteIn; // Display the discrete value. char szValueIn[12]; char szLine[81]; strcpy(szLine, "Discrete: Read = "); itoa(uValueIn, szValueIn); strcat(szLine, szValueIn); strcat(szLine, ", Should Be = "); itoa(uDiscreteValue, szValueIn); strcat(szLine, szValueIn); strcat(szLine, "\r\n"); fifoenter(szLine);
Which to avoid a 'one off' error think should be:
// Write out the value. *lpbyDiscreteOut = uDiscreteValue; // Read the discrete value back in. uint8 uValueIn = *lpbyDiscreteIn; // Display the discrete value. char szValueIn[12]; char szLine[81]; strcpy(szLine, "Discrete: Read = "); itoa(uValueIn, szValueIn); strcat(szLine, szValueIn); strcat(szLine, ", Should Be = "); itoa(uDiscreteValue, szValueIn); strcat(szLine, szValueIn); strcat(szLine, "\r\n"); fifoenter(szLine); uDiscreteValue++;
However, that doesn't explain all the anomalies in the test results. Can you post a schematic of how the EMIF write data gets connected to the EMIF read data externally to the RM48L952, and/or a scope capture of the activity on the EMIF for a write and subsequent read?
Did this test work before enabling mpu unit?
Spreadsheet shows data Bit 4 has issues!
Is D4 pin muxed? Inverted logic? or just logic timing issues?
Consult with your EE/FPGA guy to figure out the r/w timing requirements : Is Select Strobe causing issues? Did you try normal mode?
Great idea to look at binary values and compare and great catch!
Actually, bit 4 and bit 5 had issues.
I pulled the schematic for the old and new boards and sure enough bits 4 and 5 routed differently.
Discrete In Pins Discrete Out Pins
D4 15,16 13,14
D5 19,20 17,18
The other bits aligned perfectly. I had a new cable made that connected straight through with the exception of the pins above and presto!
The huge breakthrough was getting the MPU integrated and working. Creating a new sample project and copying over the default MPU settings and the comment about calling _mpu_Init_() in my code did the trick. I did not know that that function existed let alone that I need to call it.
It is sad that I cannot accept 2 answers, because the issue had 2 problems.
Thanks for all the help!