![](/img/trans.png)
[英]How can I choose different device trees from inside u-boot for the Linux kernel
[英]u-boot: how to access 'bootcount' from linux userspace?
我正在嘗試使用u-boot的“ bootcount”功能來檢測TI am335x設備(例如beaglebone黑色)上的多次引導失敗嘗試。在TI / Davinci平台上,bootcount值存儲在RTC_SCRATCH2
寄存器( 源 )中。 。 但是在Linux方面,我找不到任何將bootcount作為sysfs節點或設備公開的驅動程序,作為讀取和重置值的一種方式。 因此,似乎(主線)內核不支持此功能,但我想知道是否可以從用戶空間進行?
參考:
這是一個可行的解決方案,但是我有一個問題(請參閱下文...)
int fd = open("/dev/mem", O_SYNC | O_RDWR);
unsigned char *mem = mmap(NULL, page_offset + len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, page_base);
if (mem == MAP_FAILED) {
perror("Can't map memory");
return -1;
}
unsigned char *scratch2 = mem + page_offset;
// Read value from SCRATCH2, verify magic number
uint32_t val = *(uint32_t *)scratch2;
//printf("%08" PRIx32 "\n", val);
// low two bytes are the value, high two bytes are magic
if ((val & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000)) {
fprintf(stderr, "Error: BOOTCOUNT_MAGIC does not match\n");
return -1;
}
printf("%d\n", (uint16_t)(val & 0x0000ffff));
現在,如果我將mmap
內存轉換為uint32_t *
(如下所示),以避免以后進行類型轉換,則我讀回的值是不正確的( BOOTCOUNT_MAGIC
不匹配):
uint32_t *mem = mmap(NULL, page_offset + len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, page_base);
uint32_t *scratch2 = mem + page_offset;
// Read value from SCRATCH2, verify magic number
uint32_t val = *scratch2;
//printf("%08" PRIx32 "\n", val);
// low two bytes are the value, high two bytes are magic
if ((val & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000)) {
fprintf(stderr, "Error: BOOTCOUNT_MAGIC does not match\n");
return -1;
}
printf("%d\n", (uint16_t)(val & 0x0000ffff));
當我使用uint32_t *mem
時, val
仍應保持相同的值?
當我使用
uint32_t *mem
時,val
仍應保持相同的值?
如果您使用了正確的指針算術(沒有使用過),那么您將獲得正確的結果。
在<pointer> + <scaler>
的C表達式中,使用<scaler>
表示與指針類型具有相同大小的數量(例如sizeof(struct foo)
)。
僅當指針是字節指針時, <scaler>
表示字節計數。
如果我們有一個數組x
由一個結構的100個元素組成,例如
struct foo x[100];
數組的名稱可用作指針。
因此,數組的第十個元素的地址可以引用為&x[9]
或(x + 9)
。
因此,在您的第一個代碼示例中
unsigned char *mem ...
mem
被聲明為字節指針。
所以指針計算在
unsigned char *scratch2 = mem + page_offset;
產生您期望的結果,因為sizeof(unsigned char)
為1(字節),而page_offset
以字節數表示。
但是在第二個代碼示例中
uint32_t *mem ...
mem
被聲明為指向4字節字的指針。
因此,相同的指針計算
unsigned char *scratch2 = mem + page_offset;
真的相當於
unsigned char *scratch2 = (unsigned char *)mem + (sizeof(uint32_t) * page_offset);
其中sizeof(uint32_t)
為4(字節),並且應用的偏移量是您預期的四倍。
這是因為page_offset
仍然是多個字節,但是在原始表達式中將其視為指針類型的縮放器計數,即4字節字。
您不能簡單地更改指針類型(即,從char
更改為int
),並期望指針算術不受影響。
將mem
更改為uint32_t *
,指針計算需要重新編碼以將字節偏移量轉換為四字節偏移量:
unsigned char *scratch2 = mem + (page_offset / sizeof(uint32_t));
您可以通過使用printf()報告mem
, scratch2
和其他指針計算的值來確認這些語句(或調試代碼)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.