Using KSEG2 with wired TLB's in kernel mode - c

We have some code running in KUSEG and we see the need for more than 2Gb of memory that KUSEG provides. We tried to map some more physical memory into KSEG2 (since we run in kernel mode) by setting up wired TLBs. When I wrote a test application to access and write to the KSEG2 space (address 0xC0000000) I see that it throws a TLBS exception complaining that there is a TLB miss. I have double checked that the TLB's are setup correctly.
Am I missing something here. Has anyone used MIPS KSEG2 in kernel mode.
Thanks a lot in advance.
Vamsi.

On the chip we were using the KSEG2 address needs to have the high order 32 bits set to 1. Programming the virtual address as 0xFFFFFFFFC0000000 solved the problem.

Related

STM32F4 FSMC/FMC SRAM as Heap/Stack results in random hardfaults

we are currently evaluating to use an external SRAM for C/C++ heap storage on our platform using a STM32F439BI microcontroller.
The problem
Using the SRAM as storage for heap results in random hardfaults which are raised from buserrors/imprecice buserrors.
Without placing the heap on the SRAM, memory tests run successfully on the whole SRAM (8 bit/16 bit and 32 bit accesses).
Connecting a debugger I can observe these errors sometimes before a hardfault occurs. Most often a word is read from the SRAM and the CPU register fills with addresses of the following format: 0x-1F3-1F3 (- is most often '0', sometimes 'A' or '6'). The pattern '1F3' persists. If the same address is read again some lines further down the correct value is read (some other address in 0x60000000 space).
If I stop the program on a breakpoint at some point early in the program and step a few lines, I get these errors more frequently.
Further details
The SRAM is connected using the FMC/FSMC peripheral on FMC bank 1 and SRAM bank 1 and is therefore memory-mapped to address 0x60000000.
All settings for GPIO pins and FMC configuration are set from the startup file before main() executes or static objects are created.
The SRAM is the following: CY7C1041GN30
We connect all 16 data pins, all 18 address pins, BHE, BLE, OE, WE and CE to our controller. All pins are configured as push-pull-alternate-function, pull-up, AF_12 (FMC), very high speed. We enable clocks for all necessary pins and the clock for FMC. Note: Initially we started out without pull-up/down showing the same symptoms.
The controller runs with a clock speed of 168 MHz
As stated above, a memory test runs successfully
We use DMA for SPI, I2C and ADC data transfers
We frequently use interrupts, including external (pin) interrupts
We use the following timing settings:
AddressSetupTime: 2
AddressHoldTime: 4
DataSetupTime: 4
BusTurnAroundDuration: 1
CLKDivision: 2
DataLatency: 2
We configure the FMC as follows:
NSBank FMC_NORSRAM_BANK1,
DataAddressMux FMC_DATA_ADDRESS_MUX_DISABLE,
MemoryType FMC_MEMORY_TYPE_SRAM,
MemoryDataWidth FMC_NORSRAM_MEM_BUS_WIDTH_16,
BurstAccessMode FMC_BURST_ACCESS_MODE_DISABLE,
WaitSignalPolarity FMC_WAIT_SIGNAL_POLARITY_LOW,
WrapMode FMC_WRAP_MODE_DISABLE,
WaitSignalActive FMC_WAIT_TIMING_BEFORE_WS,
WriteOperation FMC_WRITE_OPERATION_ENABLE,
WaitSignal FMC_WAIT_SIGNAL_DISABLE,
ExtendedMode FMC_EXTENDED_MODE_DISABLE,
AsynchronousWait FMC_ASYNCHRONOUS_WAIT_DISABLE,
WriteBurst FMC_WRITE_BURST_DISABLE,
ContinuousClock FMC_CONTINUOUS_CLOCK_SYNC_ASYNC,
WriteFifo 0,
PageSize 0
We spend a lot of time of experimenting with longer timings and compared all the settings to examples including this one: Using STM32L476/486 FSMC peripheral
to drive external memories (although this one is for the STM32L4, I am fairly certain it applies to this controller as well)
Findings on similar problems
The problem sounds very similar to this errata sheet entry: "2.3.4 Corruption of data read from the FMC" but it also says the error is fixed in our revision of the controller (3)
I hope someone out there has seen this strange behaviour before and can help us. After over one week of debugging we expect some kind of error in the controller when interrupts/DMA accesses occur while the CPU accesses the SRAM (when we use it as heap, it is accessed very frequently). Hopefully you can shed some light on this topic.
Sorry for not getting back to you, internet.
Yes, we found out what the issue was (at least in our case). Problem was that the J-Link debugger we use is causing problems if it hangs above the power electronics on our pcb (it is mounted vertically). If we guide the ribbon cable out at the top (only digital electronics) the error disappears. So our guess is, that some noise from the electronics was caught up by the cable and directly injected into the JTAG port, which caused failures inside the MCU.
Just got a confirmation from ST, that there is a bug in the STM32F469 FMC that might cause incorrect values if the write fifo is disabled. The workaround is to have the fifo enabled. It is the same issue as in this F7 processor https://www.st.com/resource/en/errata_sheet/dm00145382.pdf

Linux register read arm i.mx257 from userland - devmem not working

I'm currently working on a i.mx257 platform and want to read some peripheral registers (the iomux register to be specific) to see how it is configured or if it is set right.
I've read about the devmem from busybox and devmem2, too. Tried both and both get an error. Currently there the custom board is running linux kernel version 4.6.0-rc7 from the meta-fsl-arm yocto meta package. The system is built with yocto.
root#system /]#./tmp/devmem2 0x43fac190
/dev/mem opened.
Unhandled fault: external abort on non-linefetch (0x008) at 0xb6f3a190
pgd = c3334000
[b6f3a190] *pgd=8285e831, *pte=43fac103, *ppte=43facaa2
Memory mapped at address 0xb6f3a000.
Bus error
The tool gets an Signal Err. The CONFIG_STRICT_DEVMEM option is not set in the kernel config.
I found another post http://thread.gmane.org/gmane.linux.ports.arm.kernel/26878 but I can't find some information about these registers for an i-mx25.
Is there another kernel security feature or something I'm missing?
The devmem or devmem2 is only working with values below 0x4000. For all addresses above i get the signal bus error.
Okay,
i found an answer to my own question.
The AIPS control registers have to be added to the devicetree. They are protecting the register i want to read. After i added these patches it worked.
https://github.com/torvalds/linux/commit/24bb244e02a6bead5b854d842002df0d38ae7b7b
https://github.com/torvalds/linux/commit/c33576cbf86bedf9ad3812479c3b4f36d5fadba8#diff-64c444a874c565fd98cf1ab538c1e0cd

How can I start the secondary core in Jetson TK1(arm a15)

I'm a student form China, and I'm trying to port a OS(Barrelfish) to Jetson TK1.
Now I had make the primary core working.
But when I start to deal with the secondary core, there are problems.
first, I just know using the "SEV" instruction can wake up a core (in WFE or WFI). I don't know what else i have to do?
Most important thing is I don't know how to set the secondary core's boot address.
I tried to find answer from the linux code for Jetson TK1, but I didn't find any code setting the address.
Can you tell me want i should to do?
I have got it by myself. thanks everybody who take care of this question.
In the jetson tk1 TRM, I just found that cpu fetches code from reset-vector register(in EVP register)[TRM 15.1.6.2], and the description of EVP is so simple. as follow:
EVP register
and this:
enter image description here
so I tried to write the boot address to the 0x00000000, but it made no effect.
finally, I had to try to dump memory using u-boot(md 0x0 100).
I found a useful value(0x83d8e000, the load address of u-boot) in 0x400 and 0x500 ... (from 0x400 to 0x1400)
so I tried to write the boot address of barrelfish to memory(all bytes of 0x400-0x1400), the secondary core worked!
then I tried to found the true register for secondary core, and it's 0x500.
By the way, the code to the boot secondary core is from linux.
It's all, my English is poor. if there are any errors in my words, just forgive me.

How to correctly use a startup-ipi to start an application processor?

My goal is to let my own kernel start an application cpu. It uses the same mechanism as the linux kernel:
Send asserting and level triggered init-IPI
Wait...
Send deasserting and level triggered init-IPI
Wait...
Send up to two startup-IPIs with vector number (0x40000 >> 12) (the entry code for the application processor lies there)
Currently I'm just interested in making it work with QEMU. Unfortunately, instead of jumping to 0x40000, the application cpu jumps to 0x0 with the cs register set to 0x4000. (I checked with gdb).
The Intel MultiProcessor Specification (B.4.2) explains that the behavior that I noticed is valid if the target processor is halted immediately after RESET or INIT. But shouldn't this also apply to the code of the linux kernel? It sends the startup-IPI after the init-IPI. Or do I misunderstand the specification?
What can I do to have the application processor jump to 0x000VV000 and not to 0x0 with the cs register set to 0xVV00? I really can't see, where linux does something that changes the behavior.
It seems that I really misunderstood the specification: Since the application cpu is started in real mode 0x000VV000 is equivalent to 0xVV00:0x0000. It is not possible to represent the address just in the 16 bit ip register. Therefore a segment offset for the code segment is required.
Additionally, debugging real mode code with gdb is comparable complicated because it does not respect the segment offset. When required to see the disassembled code of the trampoline at the current position, it is necessary to calculate the physical location:
x/20i $eip+0xVV000
This makes gdb print the next 20 instructions at 0xVV00:$eip.

mmap and access to GPIO config registers in an ARM processor

Im struggling to read(and write) to HW registers from Linux user space. The goal is to configure some GPIO pins from and be able to set and read this pins.
According to the spec for the processor(imx27 from Freescale) the physical address for the register bank controlling GPIO this is 0x10015000
My assumption was that I could use something like this:
unsigned long *gpio;
fd = open("/dev/mem", O_RDWR);
gpio = (unsigned long *) mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x10015000);
I now expected to be able to read and set data to the registers in the processor. The problem is that it does not matter which location I read, I always get 0.
For example register in physical location 0x10015220 contains a register showing which pins are in us as GPIO. This Defaults to 0xFFFFFFFF. Reading this register I expected to get something different than 0:
printf("PTC_GIUS: 0x%08lX\n", gpio[0x220]);
gives PTC_GIUS: 0x00000000.
Where am I going wrong ?
The mmap on /dev/mem should work. Have you tried running your code as root? Maybe some security is preventing your program from accessing the address-space. Also make sure you've passed the correct physical address of your GPIO-Space.
The approach you've used works on my Cortex-A8 ARM-board running linux without problems.
If you can't get it working there is not much you can do except finding or writing a device-driver for the gpio (writing one is not that hard btw.).
With a bit of luck someone already did that for you. Does a node named /dev/gpio exist in your filesystem? If so you already have a driver.
A google search on /dev/gpio will give you all details on how to use it. You may also find the source for a simple gpio driver that you can modify to suit your needs.
Also, if you're using a kernel source code from 2009 and on, you should open /dev/mem with the O_SYNC flag set, if you want your memory access to be uncached.
If you are using a recent version of the Linux kernel it may be blocking access to the /dev/mem device. User mode access to that device is deprecated and dangerous. It is used mainly for user mode access to video memory within X. In embedded projects it can be useful to have access to memory mapped hardware (like GPIO).
Check your Kernel compile flags for CONFIG_STRICT_DEVMEM or other flags that restrict access to /dev/mem. It could be mistakenly blocking access to this memory range.
However, as Nils mentioned the best solution is to find a gpio module for the iMX27 or write your own.

Resources