2010年3月10日 星期三

System Spec and Software Spec

What is the difference between a System Specification and a Software Specification?

Very often we find that companies do not understand the difference between a System specification and a Software Specification. Important issues are not defined up front and Mechanical, Electronic and Software designers do not really know what their requirements are.

The following is a high level list of requirements that should be addressed in a System Specification:

  • Define the functions of the system
  • Define the Hardware / Software Functional Partitioning
  • Define the Performance Specification
  • Define the Hardware / Software Performance Partitioning
  • Define Safety Requirements
  • Define the User Interface (A good user’s manual is often an overlooked part of the System specification. Many of our customers haven’t even considered that this is the right time to write the user’s manual.)
  • Provide Installation Drawings/Instructions.
  • Provide Interface Control Drawings (ICD’s, External I/O)

One job of the System specification is to define the full functionality of the system. In many systems we work on, some functionality is performed in hardware and some in software. It is the job of the System specification to define the full functionality and like the performance requirements, to set in motion the trade-offs and preliminary design studies to allocate these functions to the different disciplines (mechanical, electrical, software).

Another function of the System specification is to specify performance. For example, if the System is required to move a mechanism to a particular position accurate to a repeatability of ± 1 millimeter, that is a System’s requirement. Some portion of that repeatability specification will belong to the mechanical hardware, some to the servo amplifier and electronics and some to the software. It is the job of the System specification to provide that requirement and to set in motion the partitioning between mechanical hardware, electronics, and software. Very often the System specification will leave this partitioning until later when you learn more about the system and certain factors are traded off (For example, if we do this in software we would need to run the processor clock at 40 mHz. However, if we did this function in hardware, we could run the processor clock at 12 mHz). [This implies that a certain level of research or even prototyping and benchmarking needs to be done to create a System spec. I think it is useful to say that explicitly.]

However, for all practical purposes, most of the systems we are involved with in small to medium size companies, combine the software and the systems documents. This is done primarily because most of the complexity is in the software. When the hardware is used to meet a functional requirement, it often is something that the software wants to be well documented. Very often, the software is called upon to meet the system requirement with the hardware you have. Very often, there is not a systems department to drive the project and the software engineers become the systems engineers. For small projects, this is workable even if not ideal. In this case, the specification should make clear which requirements are software, which are hardware, and which are mechanical.

原文出處: How to write a software requirements specification



2010年2月24日 星期三

different memory address

kernel logical address: These addresses map most or all of main memory.and are often treated as if they were physical addresses. On most architectures, logical addresses and their associated physical addresses differ only by a constant offset.
内核逻辑地址和物理地址之间只有一个偏移量的差别。而且内核在启动时就是根据这种逻辑地址和物理地址的对应关系给896MB以下内存建立了页表。virt_to_phys只接受这种直接映射的虚拟地址作为参数。

kernel virtual address: ioremap返回的就是这种地址。它在VMALLOC_START和VMALLOC_END之间搜索到一块空闲的虚拟地址空间,把它和物理地址 (ioremap的参数)建立联系,并建立页表。VMALLOC_START是根据最大内存地址的虚拟地址(kernel logical address)计算出来的,如在i386中:
#define VMALLOC_START (((unsigned long) high_memory + 2*VMALLOC_OFFSET-1) & ~(VMALLOC_OFFSET-1))

可见kernel logical address和kernel virtual address 是不一样的,而且在值上是不会重叠的。对kernel virtual address调用virt_to_phys也是没有意义的。
===================================
一种就是在引导时预留RAM,如设置MEM=31M,阻止内核使用最顶部的1M字节,然后用:
dmabuf=ioremap(0x1F00000 /* 31M */, 0x100000 /* 1M */ );

我觉得你这里传给DMA的应该就是0x1F00000, 这就是物理地址,DMA所需要的。ioremap后的到的地址dmabuf是虚拟地址,是给程序用的。DMA操作完后,0x1F00000处就应该有了你要的数据,然后你就可以通过:
memcpy(dest, dmabuf, size)
操作从0x1F00000把数据复制到你想要放的地方。

你这里讲的预留1M的空间实际上已经变成了外设地址空间,因为kmalloc无法分配这块地方。


對I/O memory region寫值

Q: 假設有一個I/O addr和一個value,請說明將value寫進addr的步驟?

A:用 check_mem_region(mem_addr, mem_size) 函数来检查该内存地址有没有被用到, 可以用的话调用函数 request_mem_region(mem_addr, mem_size, "设备名称") 申请该内存,成功的话, 调用 writeb(values, mem_addr),或者 writew(values, mem_addr),writel(values, mem_addr), 来在 mem_addr 地址 写入 value 值,三个函数分别为写入 8位,16位和32位的值。 最后需要调用 release_mem_region(mem_addr, mem_size) 函数来…

I/O Resource Management

Functions (Detailed Description)

struct resource * request_region (unsigned long start, unsigned long n, const char *name)

Allocate I/O port region.
struct resource * request_mem_region (unsigned long start, unsigned long n, const char *name)

Allocate I/O memory region.
void release_region (unsigned long start, unsigned long n)

Release I/O port region.
void release_mem_region (unsigned long start, unsigned long n)

Release I/O memory region.
int release_resource (struct resource *res)

Release any resource.
int check_region (unsigned long start, unsigned long n)

Check I/O port region availability.
int check_mem_region (unsigned long start, unsigned long n)

Check I/O memory region availability.
void * ioremap (unsigned long phys_addr, unsigned long size)

Remap I/O memory into kernel address space.
void * ioremap_nocache (unsigned long phys_addr, unsigned long size)

Remap I/O memory into kernel address space (no cache).
void iounmap (void *addr)

Unmap I/O memory from kernel address space.

[新手入門] C for embeded world

if you know C, you are 50 % embedded capable. In this article, I will share a few tips that will make you an embedded qualified programmer.

1. Understand Memory Segments

Memory where the code runs can come one or more different areas called segments. These areas are simply the logical divisions that can contain suitable physical memory. To understand C code better, you need to be aware of a few common memory segments. Users can always define their segments in assembly code.


-------------------
| Text segment |
| |
|-------------------|
| Data segment |
| |
|-------------------|
| symbol table |
| |
|-------------------|
| Stack |
| |
|-------------------|
| HEAP |
| |
-------------------

1.a. Text (instructions)

This segment contains execution instructions. Normally, this segment is Read only. Programs are not generally allowed to modify the text segment. The code below will reside in the text segment.

int f() {
return 1;
}

1.b. Data Segment

This segment is used to hold global and static variables in a program. static variable, in a way, is a global variable except with limited visibility scope. A global variable/function normally has visible entry in the symbol table, whereas the static does not have an entry in the symbol table.

The globalCount variable below will reside in the data segment. Any change in its value anywhere will be effective.

int globalCount = 0;

void increment()
{
globalCount++;
}

1.c. Symbol Table

When the compiler compiles code, it puts all named entries (functions, global variables), into symbol table. The debugger uses this symbol table to go between an address and a function name. Its main purpose is for debugging/tracing.

1.d. Stack

Stack is where automatic variables stored when exceeding the number of register profile. Each program will have a default stacksize which is set by linker/compiler tool. In the example below, variable array will be allocated on the stack, whereas variable i is likely to be assigned with a register.

void functionF()
{
int array[20];
int i;
for (i = 0; i < 20; i++)
array[i] = i*i;
….
}

1.e. Heap

Heap is where operation like malloc and free operate on. It provides dynamic memory for the program. Heap is normally used for big memory buffer.

2. Know important keyword implications

When C programming was taught in school, there was little mentioning about implications of using different keywords. But rather, the coursework was probably focusing on the code construct, logic, etc… These are of course very essential for programming C, but little extra understanding would make any C course twice beneficial. Here are a few import keywords that an embedded software engineer needs to be aware of.

2.a. static keyword

static key word when combined with the variable tells the compiler to put the variable in the data segment, but limits the access scope to either a file or a function. In the code below, fileStatic variable sits in the data segment, and its scope is file meaning that any function within the same file can access to it. On the other hand, variable funcStatic is only available with functionF. funcStatic also sits in the global data segment.

static int fileStatic = 2;
void functionF()
{
int funcStatic = 1;
int array[20];
int i;
}

static is normally used by internal functions of a module. A typical use of static is shown in the snippet below

/* internal functions ... */
static void _internal1();
static void _internal2();
...
/* public functions */
int module1_function1();
int module2_function2();

2.b. volatile keyword

volatile keyword tells the compiler to use the variable from memory and not to optimize it with a register. It is typically used when the variable is shared between modules or it can be changed at anytime. Hence, any variable representing a memory location should be declared with volatile keyword.

volatile unsigned int * HardWareAddr = 0xFF00AABB;
/* read hardware register */
unsigned int a = *HardwareAddr;
/* write register */
*HardwareAddr = 0xABCDEF00;

3. Pointers and Function Pointers

Have a really good understanding about pointer and memory will take care of most of the embedded issues for you.

Pointers allow you to quickly access data at certain memory location direction, as seen in the section 2.b.

Function pointer (or also refered as function callback) is another important element of embedded world. Function pointers allow code to easily jump back and forth between functions. Most of the low level OS facilities involve function callback: Interrup Service Routine (ISR), OS context switch, user hook to OS facilities.

4. Closing

I hope that this little short article gives you some useful introduction to applying C to writing embedded applications.

參考: 原文出處

memory barrier

memory barrier 長這樣 __asm__ __volatile__("": : :"memory")

首先gcc對於匯編語言(組合語言),是使用AT&T的語法,不同於INTEL的組合語言語法

格式 : __asm__(組合語言:輸出:輸入:修飾詞")
__volatile__ 代表這行指令(這些組合語言),不和前面的指令一起最佳化
"memory" 告訴GCC這些組合語言會改變所有的RAM的資料
因為沒組合語言,又告訴gcc所有RAM的內容都改變,
所以這個memory barrier的效用,
會讓這行之前被gcc所cache到暫存器的資料通通寫回RAM裡面
也告訴gcc會讓之後讀取RAM的資料,必須再從RAM裡讀取出來

參考:原文出處

在asm裡面是說這個東西compiler時,gcc不要雞婆作optimized,因為 最佳化的結果,compiler會把code按照他想的方法放到記憶體裡, 但是有的code我們需要特定指定他一定要在某個記憶體上, 在kernel裡常有這樣情形發生,我們可以用 __asm__ __volatile__宣告一段assembly的code是不要做最佳化的。 例如cli sti
#define disable() __asm__ __volatile__ ("cli");
#define enable() __asm__ __volatile__ ("sti");

2009年11月6日 星期五

memory copy效率比較

網路上看到的一篇文章
找個時間可以來try try看
說不定這個已經是舊文不再適用也說不定 :P

==========================================

Linux下面如果要把記憶體區塊由 A 拷貝到 B,我們除了可以使用memcpy來完成以外,還可以透過mmap來開啟檔案/proc/self/mem,來完成拷貝記憶體區塊的目的。

舉個例子來說,如果我們要把記憶體區塊由A拷貝到B chunksize bytes,可以透過如下的寫法

memcpy(B, A, chunksize);

透過mmap來做的話,可以藉由以下的寫法

int self;

self = open("/proc/self/mem", O_RDONLY);

B = mmap(B, chunksize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, self, (off_t)A);

也就是透過Linux提供給每個Process的記憶體裝置檔案 mem,來完成記憶體的拷貝動作。

不過,雖然我們可以有這兩種方法可以選擇,可是遇到要拷貝記憶體時,卻不免會遇到要選擇何種方式來實做的問題,因此該網頁的作者寫了一個小程式來測試這兩種方式的優缺點,首先在Linux上每個記憶體的Page大小為512bytes,因此測試時就是利用 512 bytes為 單位來逐漸增加測試的記憶體區塊大小。每個階段都有一個固定的記憶體區塊大小,與兩個內容不同的記憶體區塊作為拷貝時的來源端,每一個循環都會先拷貝一個 來源端到目的的記憶體區塊中,再比較內容,若相同,則拷貝另一個來源端的資料到目的的記憶體區塊中,再比較內容,如此重複10000(表示共拷貝了20000次到目的記憶體區塊中),藉此來比較memcpymmap在執行記憶體區塊拷貝時的效率。

如下表

< 筆者電腦配備: PII 35064MB RAM>

memcpy

mmap

512

0.14

0.23

1024

0.26

0.35

2048

0.51

0.59

4096

1.00

1.06

8192

2.56

2.10

16384

5.67

4.55

32768

11.71

8.96

65536

23.63

17.75

我們不難發現當記憶體區塊為512102420484096時,memcpy都勝過mmap。不過當拷貝的記憶體區塊越來越大時,mmap明顯表現的相當有效率,像最後測試的記憶體區塊大小為65536 bytesmmap相較於memcpy所花的時間少了約6秒鐘。

由此我們可以了解到,如果在Linux上我們所撰寫的系統需要使用較大的記憶體區塊拷貝時,透過mmap來作或許是一個不錯的選擇。

http://loda.zhupiter.com/LinuxDynamicLibrary.htm

static library很佔flash size?

曾經聽到有人反應static library會很佔版子上的flash size
所以我想順便說明一下這中間的差別
假設分成三種case來看

1. 先不呼叫library提供的func,且當然也先不link
假設original code編好佔了約200KB

2. 一樣先不呼叫func,但在Makefile裡頭有加上-l *.a的部分
編好的ELF一樣是size不變的

3. 開始呼叫func,且作link
編好的ELF當然變大,但....size不會是等於200KB + *.a lib size
增加的部分當然只有你用到的func相關的code size
而不是整個static library size

另外
要注意的是
link是以object為單位
所以自己寫的library
最好是類似功能的,個別放單一個object
可不要通通寫成一個object
這樣就會將很多不必要的code通通link進來了

2009年11月3日 星期二

LGPL概略探討

LGPL的限制聽起來比GPL的鬆綁一些
但相信還是很多情況是讓人無所適從
所以這篇主要是作個筆記,記錄一下自己看到的一些看法

以下筆記來自:自由軟體鑄造場 林誠夏

=========================================
「自行編寫的程式與LGPL函式庫連接〈Link〉後,會不會與該函式庫結合〈Combine〉為一不可分割或很難分割的整體〈As a whole〉,而被認為整體皆為LGPL函式庫的衍生作品〈Derivative work),導致整個結合作品都要受到LGPL授權條款的拘束。」

所以、首先要探討的是,您自行編寫程式與此LGPL函式庫的調用/連結關係,行為上的判定是靜態連結〈Static link〉或是動態連結〈Dynamic link〉?

依照一般的通說,靜態連結指的是程式開啟時必然會開啟程式與該LGPL函式庫的連結關係,也就是說程式執行時對此LGPL函式庫有依賴性,若是少了這個函 式庫則整體程式幾乎沒有獨立的運作功能。在這種狀況之下,此個別編寫的程式與LGPL函式庫會被認為是一體程式,而需要整個專案都以LGPL授權的方式才 能再散布,在散布時也要提供「整個專案(自行編寫部份+LGPL函式庫)」的程式原始碼。

而若是您用dll般動態連結的方式來取用這個LGPL授權的函式庫,則表示該專案在開啟時並不會必然性的去取用/調用/連結LGPL函式庫的功能,只有在 需要某些特定功能時才去「動態式的呼叫」LGPL函式庫來得到資訊,這樣的狀況、若是除卻此一LGPL函式庫,但原來自行編寫的程式仍然具有可獨立運作的 基本功能的話,那可以視此程式與LGPL函式庫間僅為動態連結的存取關係,從而即使合併散布,但自行編寫的方式依自行律定的授權方式,而LGPL的部份則 依LGPL授權條款的方式散布,散布者原則上僅需提供LGPL函式庫部份的程式原始碼,以及該自行編寫程式與LGPL函式庫之間如何進行呼叫的 information exchange介面資訊即可。

====================================================
1、主程式啟動時直接啟動該LGPL函式庫的連結,這是靜態連結。

2、主程式啟動時並未啟動該LGPL函式庫的連結,僅在需求時才例外的呼叫LGPL的函式庫,例如一個多媒體檔案的播放程式,播放大部份媒體檔案時可以直接執行,但在播放某些特殊編碼的檔案時,才例外地去呼叫額外的LGPL函式庫來支援,這是動態連結。

所以上面的說法,常常又被簡化為:若除卻此LGPL函式庫,則主程式部份還具有基本功能者,為動態連結的利用結構;除卻此LGPL函式庫,則專案失卻主要功能者,為靜態連結的利用結構。

至於什麼才是「主要功能」或是「基本功能」,則解讀上更為見人見智。原則上必須要視個案來判定,舉個案來說,若釋出的載體是手機的話,手機的主要功能就是 撥打電話,若是除卻此一LGPL函式庫的連結造成電話無法撥打的話,那當然手機程式與此LGPL函式庫間是靜態連結的依賴關係;而若是此一LGPL函式庫 是電話簿的管理程式,若失去此一函式庫的連結,至不濟是電話簿的功能無法啟動,則「有可能」僅被判定為「動態連結」而不開啟LGPL授權條款的授權拘束 性,然而、這裡用的措詞只是「有可能」,實際上的狀況,還是要依個案來作進一步的分析。

=============================================================
我們同仁也曾經就LGPL使用Code的比例做過討論,我個人就這個議題查找的結果是,並沒有哪一個著名hacker會特別用程式碼的「比例」來判定「依賴性〈Dependency〉」。

其實LGPL授權條款裡有特別規定,原則上使用者不能去刪減該LGPL授權函式庫的功能,如果使用者主張只是單純使用這個函式庫的功能的話。

比方說您的程式只用到這個LGPL函式庫的a、b、c部份的功能,LGPL授權條款特別要求您在散布時,不要將函式庫本來有的d、e、f、g、h等功能刪 掉,LGPL授權條款向有保持該LGPL函式庫完整性的要求,因為就算您不用這些額外的功能,或許下一個得到該函式庫的使用者可能會想使用。

所以照「LGPL函式庫單純被使用原則上不能被刪改」的特性來說,該函式庫程式碼的比例會愈來愈高,這是LGPL授權預設機制所使然,在這樣的條件下,以程式碼的比例來判定依賴性也並不合理,所以從邏輯分析上、從授權者共識來說,應該都不會有這方面的問題

2009年10月23日 星期五

如何讓MAC上安裝的DPP變成英文版

相信不少MAC族友對於DPP安裝好了竟然直接顯示為簡體中文而煩惱
大家還是比較希望看到英文版本的介面
這邊分享自己試過的解決方法

首先
到系統偏好設定 -> 語言與文字
然後將Englsih暫時先拉到最上面
重開機

再次執行DPP
會發現熟悉的英文介面出現了

然後再回到系統偏好設定
將語言改回為繁體中文
再次重開機

重新執行DPP
鏘鏘鏘.....英文介面!!

有需要的族友們試試看吧~~