Wednesday, December 14, 2016

方便的網站:stackedit

**

方便的網站:stackedit

*在CMS風行一段時間之際,傳統的部落格文書編輯器已經顯得過時無用,調字體大小等這些基本功能用傳統文書編輯器還可以接受,但表格等則還需要動用html,這顯得十分麻煩,這時運用markdown方式撰寫文件的功能的網站如與後出筍般出現,包括hackmd:https://hackmd.io/專案的成功。而部落格方面,除了wordpress的markdown插件,logdown以markdown為訴求的網站平台外,如果使用傳統google所提供的blogger功能的話,首推stackedit:https://stackedit.io,他的功能十分強大,可以幫你管理你的文章還可以串連多個blog平台,包括blogger,wordpress,github,gist,tumblr等,而且畫面簡潔明亮,害我都跳槽了哈哈。

Written with StackEdit.

Wednesday, December 7, 2016

[Note]Microcontroller的排程方式

[Note]Microcontroller的排程方式

這篇為我看完Microchip Technology 20024 FRM4 - Interrupt and Task Scheduling - No RTOS Required後所作的筆記。

Race condition與Synchronization

Race condition的觀念在恐龍書已經說很多了,所以就不提了。而Synchronization部份,Microcontroller常用interupt disabling和spin lock來做處理,而用到sempahore的部份也是有。另外值得注意的一點是,由於MCU同時有許多peripheral component(Timer,ADC,SPI,UART...)再運作,這些元件也會改變SFR(special function register)的值,所以建算你的程式是但執行序,仍可能會有race consition發生,例如:在PIC的 16 bit timer中,他是分成兩個register控制timer的值(TMR1L,TMR1H),也就是說你要更動timer的值時,需要大於兩個cycle,才可辦到,但是如果在存取值的時候你的timer仍在運作,則可能發生,不合理的狀況。比方說你想要讀取TMR1的值(TMR1H + TMR1L),原本TMR1H = 0x00,TMR1L = 0xFF,第一部份,你讀到了TMR1H的值為0x00,但在第二部份時你要讀TMR1L的時候,因為timer仍在計時,經過一個cycle,TMR1L的值已經加1並進位到TMR1H,所以TMR1L的值現在為0x00,你讀到的值就是0x00,在這個case中,你預期你會得到(0x00,0xFF),但你實際上拿到(0x00,0x00),這是在MCU常有的情況。避免的方法為暫停timer然後再去取值。


Review interrupt

在MCU中硬體發生的中斷會已硬體的context switch實做,也就是她會將當前的core register複製一份到shadow register儲存,保留狀態,當離開ISR後,CPU會將shadow register載回core register中。

在interupt中,對於跨ISR與main line的變數,可以考慮使用Volatile修飾字(一個資源有多個process使用時,透過這個修飾字可以告訴編譯器,不要對這個值做值域判斷優化),以免編譯器編出你無法預期的行為。

interrupt在context switch時會有所謂的interrupt latency(在IVT中尋找對應的interrupt vector+context switch+當前指令的完成(例如說MUL)),這是MCU的效能指標之一,不過對於多層的interrupt,在第二層以後失去了硬體context swtich的優化,所以速度會慢很多。

Jitter injection為main line在被中斷後所暫停執行的時間,通常要盡量讓Jitter 愈小愈好。

interupt priority:MCU中的interrupt有priority,規範誰可以中斷誰,例如說PIC18F系列有兩個level,dsPIC30F系列有八個level,此外MCU中透過interrupt 在IVT的順序,有所謂的natural order priority,來處理相同level intertupt同時發生的問題。另外,ISR裡可以包裹多個interrupt handler,這部份一樣是透過IVT先後和priority還有發生時間決定進入點。(其他:可重入程序)。

一些ISR設計的注意細節:
1.盡量ISR短,減少jitter
2.避免無限的等待
3.盡量避免ISR與mainline使用相同的全域變數(有的話記的要加volatile)

Review scheduler(非Real time)與相關技術

有cooperative與preemptive兩大類,恐龍書有詳盡描述。此外還有兼容兩種特性的(hybird)。

常見排程方式與技術有:

1.sequential

任務是循序執行的,好處是簡單明瞭,非常好預期行為。缺點是容易多做一些不必要的任務,還有每個任務的latency變異大。

2.Round Robin

恐龍書有提到,就跳過了。

3.basic priority與advanced priority

透過簡單邏輯判斷該執行哪些任務,壞處是要維護判斷的變數狀態正確性,還有避免starvation,而且當判斷模式複雜時難除錯。


4.staged

透過將任務拆解成多個stage然後使用FSM的方式管理任務執行順序,缺點是增加許多資源管理state。


5.scheduled(這裡指時間上)

透過規劃何時該做什麼達成scheduled,好處是簡單好讀,執行時間可預期,好擴展。缺點是需要Timer來排行程,還有有需要維護Ticker。






Tuesday, December 6, 2016

C99 fast data type

C99 fast data type

這個主題是我在看完Efficient C Tip #13 – use the modulus (%) operator with caution這篇文章發現的C99在stdint.h新規範的一些資料型態,所作的小小理解。

C99 fast data type,為一種針對硬體CPU架構所提出的資料型態。主要有這下列八種型態:
uint_fast8_t        
uint_fast16_t
uint_fast32_t
uint_fast64_t
int_fast8_t        
int_fast16_t
int_fast32_t
int_fast64_t
在C99 7.18.1.3是這樣做定義的:
1 Each of the following types designates an integer type that is usually fastest 219) to operate
with among all integer types that have at least the specified width.
2 The typedef name int_fastN_t designates the fastest signed integer type with a width
of at least N . The typedef name uint_fastN_t designates the fastest unsigned integer
type with a width of at least N .
也就是說,這些fast data type確保,你的型態至少為N bit以上(uint_fast8_t至少有8bit width),所以有可能你
宣告一個uint_fast8_t的型態,編出來可能是用16bit裝。
這個型態最重要的用意是aliginment(對齊),一般來說16bitCPU在處理16bit的資料運算有可能8bit的快,這是因為
對齊的因素,因此,這些fast data type在這個例子中直接將uint_fast8_t 定義為uint16_t,來方便CPU運算。

以下這是給16bit MCU的compiler microvhip XC16,在stdint.h中的定義
#ifndef uint_fast8_t                                                            
typedef unsigned int uint_fast8_t;                                              
#define uint_fast8_t uint_fast8_t                                               
#define UINT_FAST8_MAX (65535UL)                                                
#endif  
很明顯可以看到她將uint_fast8_t用unsigned int(16bit)來使用。

Efficient C Tip #13 – use the modulus (%) operator with caution中在16bit的MSP430,作者僅將型態改成,
fast data type,就得到了大幅的加速。在MCU等小型硬體中,在適當的地方使用C99 fast data type可以得到很好的效果。



Wednesday, September 28, 2016

『note』目前的vim

『note』目前的vim

本文僅僅紀錄我用了什麼vim plugin。

首先.vimrc


  • 基本設定

set shiftwidth=4
set expandtab
set softtabstop=4
set laststatus=2
set noshowmode
set number
set modeline
set t_Co=256
set tabstop=2
set fileencodings=utf-8,big5
set cursorline                                                                                                                                    
set mouse=a
syntax on


  • 編譯快捷鍵

autocmd filetype python nnoremap  :w  exec '!python '.shellescape('%')
autocmd filetype c nnoremap  :w  exec '!clear&&gcc '.shellescape('%').' -o '.shellescape('%:r').'&&./'.shellescape('%:r') 
autocmd filetype cpp nnoremap  :w  exec '!clear;echo -n "====================";TEMP=`mktemp`;script $TEMP -e -q -c "g++ '.shellescape('%').' -std=c++11 -Wall -o '.shellescape('%:r').'" > /dev/null 2>&1 ;if [ $? == 0 ] ;then echo -e "\r\033[32m********************\033[0m";./'.shellescape('%:r').';else echo -e "\r\033[31mXXXXXXXXXXXXXXXXX\033[0m";cat $TEMP; fi'                                                                
autocmd filetype c nnoremap  :w  exec '!clear&&gcc '.shellescape('%').' -o '.shellescape('%:r') 
autocmd filetype cpp nnoremap  :w  exec '!clear&&g++ '.shellescape('%').' -std=c++11 -Wall -o '.shellescape('%:r')
nnoremap  :w  exec '!cat '.shellescape('%').'\| xclip -selection clipboard'
nnoremap  :w  exec '!fish'

  • 主題:tomorrow

Bundle
Bundle 'chriskempson/tomorrow-theme', {'rtp': 'vim/'}
設定
color Tomorrow-Night-Bright
colorscheme Tomorrow-Night-Bright

  • neocomplcache

補完插件
Bundle
Bundle 'Shougo/neocomplcache.vim'  
設定
"neocomplcache                                                                                                                                    
let g:neocomplcache_enable_at_startup = 1
let g:neocomplcache_disableautocomplete = 1
let g:neocomplcache_enable_smart_case = 1
" Recommended key-mappings.
" <CR>: close popup and save indent.
let g:neocomplcache_enable_insert_char_pre = 1
  • nerdtree
檔案樹插件
Bundle
Bundle 'scrooloose/nerdtree'
設定
let NERDTreeWinPos='left'
let NERDTreeWinSize=30
map <F2> :NERDTreeToggle<CR>

  • vim-gitgutter

vim git狀態(插入與刪除等)
Bundle


Bundle 'airblade/vim-gitgutter'


  • xterm-color-table.vim

xterm的顏色表
Bundle

Bundle 'guns/xterm-color-table.vim'


  • vim-cuteErrorMarker

語法錯誤標記
Bundle

Bundle 'Twinside/vim-cuteErrorMarker'

  • vim-better-whitespace

行尾空白顯示
Bundle
Bundle 'ntpeters/vim-better-whitespace'
設定
hi ExtraWhitespace ctermbg = 17


  • indentLine

縮排圖示
Bundle
Bundle 'Yggdroot/indentLine'


  • vim-l9

vim script library
Bundle
Bundle 'eparreno/vim-l9'

  • vim-json

vim json syntax highlight
Bundle
Bundle 'elzr/vim-json'

  • syntastic

自動語法檢查
Bundle
Plugin 'scrooloose/syntastic'
設定
set statusline+=%#warningmsg#

set statusline+=%{SyntasticStatuslineFlag()}
set statusline+=%*

let g:syntastic_always_populate_loc_list = 1
let g:syntastic_auto_loc_list = 1
let g:syntastic_check_on_open = 0
let g:syntastic_check_on_wq = 1
let g:syntastic_cpp_compiler = 'g++'
let g:syntastic_cpp_compiler_options = ' -std=c++11 '
let g:syntastic_c_compiler = 'gcc'
let g:syntastic_c_compiler_options = ' -ansi'
let g:syntastic_javascript_checkers = ['standard']
let g:syntastic_javascript_standard_generic = 1
let g:syntastic_javascript_checkers = ['eslint']
let g:syntastic_javascript_eslint_exec = 'eslint'

  • YouCompleteMe

補完工具
Bundle
Bundle 'valloric/YouCompleteMe'
設定
let g:ycm_global_ycm_extra_conf = $HOME/.vim/bundle/YouCompleteMe/third_party/ycmd/cpp/ycm/.ycm_extra_conf.py'



  • tagbar

C/C++ taglist
Bundle

Bundle 'majutsushi/tagbar'

設定


nmap  :TagbarToggle           
let g:tagbar_ctags_bin='ctags'         
let g:tagbar_width=30                
map  :Tagbar
autocmd BufReadPost *.cpp,*.c,*.h,*.hpp,*.cc,*.cxx call tagbar#autoopen()

Saturday, September 24, 2016

John Murphy:特殊風格的電影配樂家

John Murphy:異軍突起的電影配樂家

首先先貼他的個人網站http://johnmurphyofficial.com/

他最有名的三首配樂是『28天毀滅倒數(28 days later)』的『In the house,In the heartbeat』把活屍的壓迫感形容的很好,有興趣還可以聽聽看續集『28周毀滅倒數(28 weeks Later)』的開頭男主角的爸爸被追趕的那段,十分精彩,循環覆呇的節奏與逐漸加強的重音,就像一隻隻活屍在你身後快速的逼近你,即使你逃過當時,你有遠也不知道牆後是否還有另一隻在伺機而動。

第二首是同樣是Danny Boyle執導的『太陽浩劫(sunshine)』中的『Sunshine (Adagio in D Minor)』,這首曲子聽起來十分雄壯,有太陽的感覺。這首有名的點是她常出現在電影預告、商品廣告中,維基百科還有條目在統計他出現在那。包括Star Trek:Into Darkness、Kick Ass、X-men、The Adjustment Bureau還有Samsung的Smart TV廣告。其他運用這首的都在這https://en.wikipedia.org/wiki/Sunshine:_Music_from_the_Motion_Picture

第三首是驚悚片:『左手邊的那棟房子』的配樂,不過這部電影我沒看過就不做評論了。

Tuesday, September 20, 2016

[偷書賊]偷書賊與過於喧囂的孤獨

[偷書賊]偷書賊與過於喧囂的孤獨

偷書賊講述的是一個二戰時期一個德國小女孩靠著文字豐富自己心靈的故事,其中穿插著二戰時期生活環境的疲敝,還有人性的本質。

而赫拉巴爾的<過於喧囂的孤獨>則是以一個在廢紙回收廠的老員工,在工作之餘將書中知識收入自己的腦海,然而,其身處於社會的角落,還做著將書本壓成廢紙的工作,雖然學識涵養豐富,但作著一般人鄙視、無視的工作。其內心是過於喧囂的孤獨。

這兩本書一個是從剛識字的小孩角度看待文字的影響力,一個是從滿腹學識的老人在知識的翻騰中對比自身的孤獨感。同樣都是以文字的力量出發,但在人生起始階段與人生終老階段,文字以不同的方式影響著人們。

這兩本書都蠻推薦的(偷書賊較淺白)。

Saturday, September 10, 2016

在linux上製作win10 live USB

在linux上製作win10 live USB

這部份很簡單,只要記住一個重要的程式『winusb』,安裝這個程式,一切都簡單。

首先,以arch linux 為例,winusb是在aur裡,所以只要下:

yaourt -Sy winusb

即可安裝。

接著開始製作live usb,先找到win10 ISO 檔的路徑,還有你的隨身碟隨身碟掛載路徑,下以下指令:

winusb --install <iso path> <partition>

記得要用root or sudo來做。即可完成。

Friday, September 9, 2016

快閃大對決:一場華爾街起義

快閃大對決:一場華爾街起義

我會找到這本書完全是因為這本書的作者是<魔球>、<攻其不備>、<大賣空>的作者,我蠻喜歡他的寫作風格。這本書算是他在台最新的(雖然是2014年的)。
***
這本書主要探討近年來美國股市興起的高頻交易如何危害市場,雖然我以前就有聽過『高頻交易』這個詞,但我沒想到它的實際運作方式這麼恐怖。美國現在有13個交易所交易所(還有60幾個暗池)之間彼此都有一些距離,有些在紐約,有些在芝加哥,即便現在通訊技術發達,但這些交易系統否此間的資訊仍有幾毫秒的差距,所以如果你能在資訊從一個交易所到另一個交易所之間提前買賣股票,就等於是在買樂透時提前知道結果然後進行下注。或者是在別人買股票前提前插隊將股票買走,然後用更高的價格賣回給買家。基本上所有交易操作都在毫秒內快速來回。這造成了股市成交量爆增、波動劇烈、還有快閃崩盤,在加上股票是一個趨近於零和的賽局,當有人在你買賣間先進行了一次交易,等於是從你身上扒了一層皮。
***
最後有群人為了打擊高頻交易,設計了一個慢市交易所(IEX),讓所有交易都慢了330us而且個交易所的資訊到這個交易所的時間差都相同,使高頻交易失去套利空間,但這場與高頻交易間的戰爭仍在大股市間上演,高頻交易仍存在於市場。
***
現在的股票市場上冒出了一個新種族(bot),這些程式在取代大量傳統交易員,在毫秒間改變市場走向,操縱著市場。
***
這不是Fintech什麼才是Fintech?(誤)

Wednesday, August 31, 2016

Jekyll 一些問題解法

用github架Jekyll 一些問題解法

當一開始使用

jekyll serve
view raw jekyll serve hosted with ❤ by GitHub

的時候,可能會遇到一些問題(其實是我遇到的啦)

jekyll serve not found

這是一個很好處理的問題,因爲你的~/.gem/ruby/{version}/bin資料夾沒有在$PATH路徑下。加上去就可解決了。

缺少bundler
kernel_require.rb:55:in `require': cannot load such file -- bundler (LoadError)

大概的error如上。處理方式很簡單,就是安裝bundler。


$gem install bundler

這樣就解決了。
如果還有以下錯誤:
resolver.rb:356:in `block in verify_gemfile_dependencies_are_found!': Could not find gem 'jekyll-sitemap' in any of the gem sources listed in your Gemfile or available on this machine. (Bundler::GemNotFound)
則多下一行指令:
$ bundle install --path vendor/bundle

invalid date ...YAML..

跑jekyll serve的時候可能會有噴出一堆如下的錯誤。

Invalid date '<%= Time.now.strftime('%Y-%m-%d %H:%M:%S %z') %>': Document 'vendor/bundle/ruby/2.3.0/gems/jekyll-3.2.1/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb' does not have a valid date in the YAML front matter.
view raw YAML error hosted with ❤ by GitHub

處理方法稍微麻煩一點。找到repo底下的_config.yml檔案,在約第五行
...
...
...exclude:[......,"vendor"...]
的exclude中加入vendor。

一些asset link出錯

我自己在架的時候他的一些bootstrap的css和js檔案link不到,原因是它要link的連結在
assets/themes/bootstrap-3下,但其原本目錄並沒有這個子目錄,所以在assets/themes下建立bootstrap-3,並將原本的bootstrap移到底下。



Wednesday, August 24, 2016

HackNTU2016小小心得

HackNTU2016小小心得

其實我本身已經去過去年(2015)的HackNTU了,所以這篇文章會稍微比較這兩年。HackNTU為台灣規模最大的hackthon,但其核心價值已經逐漸遠離黑客松的"合作"、"效率"、"有用"、"有趣"的精神了。hackNTU逐漸變成一種比賽,創業比賽。我個人認為有好有壞。好處讓hacker可以更有商業頭腦,除了設計搞怪小東西外,還可以走進市場,同時,由於評審來自商業界,有種吸引創投的fu。壞處當然就是過度商業化得黑客松已經變成創業松,一堆人拿早就跑很久的專案進來投,失去了黑客松該有的短期高效合作模式,另外過度傾向賺錢,偏離了其實這是一個技術性活動,一些不好的事情就這樣發生了:"簡報松"、"不會coding只做簡報拿獎"、"SetTimeout"。這樣失去了hacker們自我實現與實做的目標了。

今年由於受到COSCUP的撞期影響,人數大減3~4成,加上去年的風評不佳(評審問了『你怎麼賺錢』、『你怎麼make money』、『你的business model是什麼』)造成在社群間不好的名聲流傳。不過今年其實沒這個問題,評審都問一些本質與技術,這是一個好現象。可能因為人數大減的原因,使得今年食物較少(食物也是黑客松的精華阿),肥宅我的心得試吃不飽。

今年贊助廠商變多,變得多元,不過兩排排了一排攤位,大投影牆還播著廣告,害我以為我來到世貿之類的地方了XD。

Tuesday, August 16, 2016

[tools]GNU 開發工具:nm

[tools]GNU 開發工具:nm

nm

nm這東西是來列出object files(binary file)的符號(symbol),包括列出地址(address)、類型、名稱。
以下我打了一個範例。

#include<stdio.h>
void foo(){
printf("bar");
}
int Global_var;
int Global_var_init = 0;
int main()
{
int local_var;
int local_var_init = 0;
int a = local_var_init + Global_var_init;
foo();
}

接下來是對其編譯出來的a.out下nm指令的結果。


0000000000601030 B __bss_start
0000000000601030 b completed.6916
0000000000601020 D __data_start
0000000000601020 W data_start
0000000000400430 t deregister_tm_clones
00000000004004b0 t __do_global_dtors_aux
0000000000600e10 t __do_global_dtors_aux_fini_array_entry
0000000000601028 D __dso_handle
0000000000600e20 d _DYNAMIC
0000000000601030 D _edata
0000000000601040 B _end
00000000004005b4 T _fini
00000000004004f6 T foo
00000000004004d0 t frame_dummy
0000000000600e08 t __frame_dummy_init_array_entry
0000000000400718 r __FRAME_END__
0000000000601000 d _GLOBAL_OFFSET_TABLE_
0000000000601038 B Global_var
0000000000601034 B Global_var_init
w __gmon_start__
00000000004005c8 r __GNU_EH_FRAME_HDR
00000000004003c8 T _init
0000000000600e10 t __init_array_end
0000000000600e08 t __init_array_start
00000000004005c0 R _IO_stdin_used
0000000000600e18 d __JCR_END__
0000000000600e18 d __JCR_LIST__
00000000004005b0 T __libc_csu_fini
0000000000400540 T __libc_csu_init
U __libc_start_main@@GLIBC_2.2.5
000000000040050c T main
U printf@@GLIBC_2.2.5
0000000000400470 t register_tm_clones
0000000000400400 T _start
0000000000601030 D __TMC_END__
view raw nm_out_test hosted with ❤ by GitHub

第一列為地址,第二列為類型,第三列為名稱。類型部份可以man一下nm。以下是擷取自man nm。

DESCRIPTION
GNU nm lists the symbols from object files objfile.... If no object files are listed as arguments, nm assumes the file a.out.
For each symbol, nm shows:
· The symbol value, in the radix selected by options (see below), or hexadecimal by default.
· The symbol type. At least the following types are used; others are, as well, depending on the object file format. If lowercase,
the symbol is usually local; if uppercase, the symbol is global (external). There are however a few lowercase symbols that are
shown for special global symbols ("u", "v" and "w").
"A" The symbol's value is absolute, and will not be changed by further linking.
"B"
"b" The symbol is in the uninitialized data section (known as BSS).
"C" The symbol is common. Common symbols are uninitialized data. When linking, multiple common symbols may appear with the same
name. If the symbol is defined anywhere, the common symbols are treated as undefined references.
"D"
"d" The symbol is in the initialized data section.
"G"
"g" The symbol is in an initialized data section for small objects. Some object file formats permit more efficient access to small
data objects, such as a global int variable as opposed to a large global array.
"i" For PE format files this indicates that the symbol is in a section specific to the implementation of DLLs. For ELF format
files this indicates that the symbol is an indirect function. This is a GNU extension to the standard set of ELF symbol types.
It indicates a symbol which if referenced by a relocation does not evaluate to its address, but instead must be invoked at
runtime. The runtime execution will then return the value to be used in the relocation.
"I" The symbol is an indirect reference to another symbol.
"N" The symbol is a debugging symbol.
"p" The symbols is in a stack unwind section.
"R"
"r" The symbol is in a read only data section.
"S"
"s" The symbol is in an uninitialized data section for small objects.
"T"
"t" The symbol is in the text (code) section.
"U" The symbol is undefined.
"u" The symbol is a unique global symbol. This is a GNU extension to the standard set of ELF symbol bindings. For such a symbol
the dynamic linker will make sure that in the entire process there is just one symbol with this name and type in use.
"V"
"v" The symbol is a weak object. When a weak defined symbol is linked with a normal defined symbol, the normal defined symbol is
used with no error. When a weak undefined symbol is linked and the symbol is not defined, the value of the weak symbol becomes
zero with no error. On some systems, uppercase indicates that a default value has been specified.
"W"
"w" The symbol is a weak symbol that has not been specifically tagged as a weak object symbol. When a weak defined symbol is
linked with a normal defined symbol, the normal defined symbol is used with no error. When a weak undefined symbol is linked
and the symbol is not defined, the value of the symbol is determined in a system-specific manner without error. On some
systems, uppercase indicates that a default value has been specified.
"-" The symbol is a stabs symbol in an a.out object file. In this case, the next values printed are the stabs other field, the
stabs desc field, and the stab type. Stabs symbols are used to hold debugging information.
"?" The symbol type is unknown, or object file format specific.
· The symbol name.
view raw man_nm hosted with ❤ by GitHub

這個工具可以幫助我們了解object file的資料layout,函式定義等,對於無source code只有object files的開發者來說十分方便(有source code可用compiler的參數來分析)。

nm可以幫助我們分析undefined reference狀況與data的分區(bss,text,data)。

相關連結:1.http://www.wuzesheng.com/?p=1595
                 2.http://sp1.wikidot.com/elfobjfile
                 3.http://enginechang.logdown.com/posts/248172-linker-loader-library
            4.https://github.com/torvalds/linux/blob/9256d5a308c95a50c6e85d682492ae1f86a70f9b/arch/powerpc/boot/elf.h

用Compiler Explorer學習C/C++的效能與實做

用Compiler Explorer學習C/C++的效能與實做

今天我發現一個網站:compiler explorer,這個網站可以將C和C++即時編譯為組語,而且寒可以選AT&T語法的nasm和INTEL語法的nasm,對於底層學習很有幫助。

支援

這個網站支援ARM、MIPS、X86、AVR等指令集的compiler,支援度甚廣,且網頁本身也開源(使用node.js),連結:https://github.com/mattgodbolt/gcc-explorer

操作畫面


Friday, August 5, 2016

使用Ardunio Atmega2560 連接 nRF24L01+

使用Ardunio Atmega2560 連接 nRF24L01+

關於library

其中TMRh20大大做的這個還可支援linux(Raspberry pi),支援度較廣。不過本篇文章選用maniacbug大大的library。

mega2560連接nRF24L01

以下是nRF24L01 模組的照片與pinout。

從左上開始,右下結束。
                           
1.GND2.VDD(3.6V以下)
3.CE4.CSN
5.SCLK6.MOSI
7.MISO8.IRQ


Mega2560部份,我們不需要接IRQ,因為library沒有實做,讀者有興趣可以修改library中關於nRF24L01一個名叫config的暫存器,將mask中斷的部份歸零。

Mega2560的部份需要其上頭內建的SPI BUS,才能使用這個函式庫(TMRh20的library有提供Software SPI應用)。以下是Mega2560的SPI接腳對應。



SCK要接nRF24L01的SCLK,MOSI接MOSI,MISO接MISO,CE和CSN可自行定義腳位。

程式碼部份直接利用官往提供的example來做測試。
http://maniacbug.github.io/RF24/GettingStarted_8pde-example.html
原始碼中RF24物件建構子這行
RF24 radio(9,10);
9表示CE接腳,10表示CSN接腳。

程式運行時可以開啟Serial port monitor來觀察其運作,其中他在radio.printDetails();部份印出的細節可以多留意,尤其是收發兩端的address,在TX_ADDR那項兩邊要不同。接下來就可開心的看著她發送了。

連不上的一些解法

地址錯誤

兩邊的地址要可對到,一邊RX_ADDR要為另一邊TX_ADDR,這樣才可收到。

雜訊

有些nRF24L01模組的電源供應沒有電容濾波,可以自行用電容跨接GND和VCC兩端,建議選擇10uF到50uF的電容,另外模組的GND要和Ardunio的GND共地(從Ardunio直接拉GND是好選擇)。

傳輸速率過快

example預設為2Mbps,可自行降為1Mbps,有機會收到較佳的訊號。

Sunday, July 31, 2016

PWM產生方式

PWM簡述

PWM為Pulse Width Modulation的縮寫,對於只有high和low的數位訊號來說,如何用high,low比率調整出類似類比訊號為PWM的用處,另外大多數馬達也透過PWM來驅動轉速,LED由於只吃固定電壓,所以常用PWM來調整亮度。
duty cycle(占空比)為整個high時間除以週期時間(D = DT/T)。

PWM產生方式

PWM主要又三種方式產生:硬體內建PWM模組、中斷產生、迴圈。

硬體內建PWM模組

MCU內常內建PWM模組,以PIC系列為例,有CCP(Capture/Compare/PWM)模組、Output Compare模組和PWM模組。透過設定timer和暫存去達成PWM輸出。以下以dsPIC30F4013的Output Compare做示範。


#include <xc.h>
// FOSC
#pragma config FOSFPR = XT_PLL4 // Oscillator (XT w/PLL 4x)
#pragma config FCKSMEN = CSW_FSCM_OFF // Clock Switching and Monitor (Sw Disabled, Mon Disabled)
// FWDT
#pragma config FWPSB = WDTPSB_16 // WDT Prescaler B (1:16)
#pragma config FWPSA = WDTPSA_512 // WDT Prescaler A (1:512)
#pragma config WDT = WDT_OFF // Watchdog Timer (Disabled)
// FBORPOR
#pragma config FPWRT = PWRT_64 // POR Timer Value (64ms)
#pragma config BODENV = BORV20 // Brown Out Voltage (Reserved)
#pragma config BOREN = PBOR_ON // PBOR Enable (Enabled)
#pragma config MCLRE = MCLR_EN // Master Clear Enable (Enabled)
// FGS
#pragma config GWRP = GWRP_OFF // General Code Segment Write Protect (Disabled)
#pragma config GCP = CODE_PROT_OFF // General Segment Code Protection (Disabled)
// FICD
#pragma config ICS = ICS_PGD // Comm Channel Select (Use PGC/EMUC and PGD/EMUD)
#define Tcy 10000000 //10MHz oscillator with 4xPLL -> 10'000'000MIPS
//------------------------------------------------------------------------------
// main routine
//------------------------------------------------------------------------------
int main(int argc, char** argv) {
//------------------------------------------------------------------------------
// IO Plan
TRISA = 0x0000;
TRISB = 0x0000;
TRISC = 0x0000;
TRISD = 0x0000; //RD1,RD2,RD3,RD4 -> PWM OC pin
TRISF = 0x0000;
ADPCFG = 0xFFFF;
//------------------------------------------------------------------------------
// initialize PWM
//PR2 = 50000; 1:256-> 200 HZ
PR2 = 25000;
OC1RS = 1875;
OC1CON = 0x0006; //Set PWM mode on OC1,Fault pin disable,Timer2 is source
OC2RS = 1875;
OC2CON = 0x0006; //Set PWM mode on OC2,Fault pin disable,Timer2 is source
OC3RS = 1875;
OC3CON = 0x0006; //Set PWM mode on OC3,Fault pin disable,Timer2 is source
OC4RS = 1875;
OC4CON = 0x0006; //Set PWM mode on OC4,Fault pin disable,Timer2 is source
//IEC0bits.T2IE = 1; //enable Timer2 interrupt
// T2CON = 0x8000; //Configure Timer2(Timer on,continue in IDLE,not gate
// ,1:256 prescaler,internal clock)
T2CON = 0x8010;
TMR2 = 0;
while(1);
}
}


由於每個MCU的PWM實際細節都不一樣,所以讀者請自行閱讀datasheet來應用硬體內建的PWM。
dsPIC30F系列的Output Compare PWM模組要應用時須將OCxCON 暫存器中的OCM設為'110'或'111'。設定順序為:
1.設定PRy(Period register)表示PWM的週期。
2.再來設定OCxRS暫存器表示duty cycle。
3.設定OCM。
4.設定timer,並開啟timer。

PWM 週期 = [(PRy+1)]*Tcy*(TMRx presclaer value)。 (Tcy為振盪器頻率*PLL/4)
PWM 頻率為週期倒數。
詳細設定在http://ww1.microchip.com/downloads/en/DeviceDoc/70157C.pdf中有詳細描述。

中斷產生PWM

利用Timer中斷來切換PWM進入duty cycle,有兩種方法。

一、用一個或兩個timer,先輸出high,計算PWM在high所需時間,設定好Timer 週期(中斷條件),當Timer發生中斷,將輸出切為low,並在計算PWM在low所需時間,同樣設定好Timer週期,當Timer發生中斷回到一開始重頭來過。也可用兩個Timer一個設為high所需時間,一個為period,當high的timer 中斷發生,關閉其中斷與timer,並將輸出設為low,等待period 的Timer發生中斷,在開啟high 的timer中斷。

二、用一個timer中斷,當其中斷將counter加一,一旦couner的值大於duty cycle則切為low,當counter的值大於period則歸零。以下為範例(使用PIC18F452)。
/*
* File: newmainXC16.c
* Author: asus-h
*
* Created on 2015?2?9?, ?? 9:49
*/
#include "xc.h"
#pragma config OSC = HS, WDT=OFF, LVP=OFF,PWRT = OFF
int counter,pwm_val_1 = 20,pwm_val_2 = 20,pwm_val_3 = 20,pwm_val_4 = 20;
int change = 1;
void init_timer();
void do_PWM();
int main(void) {
TRISC = 0xEF;
TRISB = 0b11111111;
TRISD = 0x00;
//TRISCbits.TRISC4 = 0;
//unsigned int duty = 500;
// T3CONbits.T3CCP2=0;
// T3CONbits.T3CCP1=0;
INTCON2 = 0b00000001;
init_timer();
return 0;
}
void interrupt ISR()
{
if(T0IF)
{
TMR0 = 65530;
counter++;
INTCON &= ~(1<<T0IF);
//INTCON = 0b11111110; //clear overflow bit;
T0IF = 0;
do_PWM();
}
}
void init_timer()
{
TMR0 = 65500;
TMR1 = 0;
T0CON = 0b10000001;
T1CON = 0b10000000;
//OPTION = 0B00001000;
INTCON = 0b11111110;
PIR1 = 0b000000011;
}
void do_PWM()
{
TMR0 = 65530 ;
counter++;
if(counter<=pwm_val_1)
PORTDbits.RD4 = 1;
else
PORTDbits.RD4 = 0;
if(counter<=pwm_val_2)
PORTDbits.RD5 = 1;
else
PORTDbits.RD5 = 0;
if(counter<=pwm_val_3)
PORTDbits.RD6 = 1;
else
PORTDbits.RD6 = 0;
if(counter<=pwm_val_4)
PORTDbits.RD7 = 1;
else
PORTDbits.RD7 = 0;
if(counter == 100)
counter = 0;
T0IF = 0;
}


此方法缺點為PWM頻率難以調整,不過對於本身PWM模組缺乏或過少之MCU,此法十分有效。

迴圈產生PWM

以迴圈直接產生PWM,可以用一個counter當作現在情況,當迴圈執行次數超過duty cycle的值時,調整high low,這方法十分簡單,但如果要有準確的頻率需要將程式編成組語計算其所需時間,並用NOP指令挑整週期。這方法會佔走整個CPU,十分無效率,但其可以結合輪詢等固定時間需要執行的功能,對於低階,簡單的系統有其應用空間。


Sunday, May 8, 2016

[筆記] libpqxx - prepare statements

prepare語法是現今SQL主要防止SQL injection的方法(另一種是字串處理),prepare語法主要是限定SQL query語句中的變數,以防資料庫其他資料遭受破壞等。postgresSQL也有prepare語法。請見:http://www.postgresql.org/docs/9.1/static/sql-prepare.html

而libpqxx中也有prepare method。這個prepare框架一旦被定義後,它會存活於connetion物件存活期間(連線期間)。底下是範例,其中prepare_name爲使用者自定(case sensitive),之後會用到。

connection C(/*user parameter*/);
C.prepare("prepare_name","SELECT NAME FROM TESTTABLE WHERE id = $1");
再來是傳遞變數進入prepare的框架。

connection C(/*user parameter*/);
pqxx::work W(C);
C.prepare("prepare_name","SELECT NAME FROM TESTTABLE WHERE id = $1");
pqxx::result r = W.prepared("prepare_name")(ID).exec();
W.commit();
其中傳變數方法還有其他寫法,請見:http://stackoverflow.com/questions/31833322/how-to-prepare-statements-and-bind-parameters-in-postgresql-for-c

prepare方法有時會降低效率,其他細節都在官方paper中。

Sunday, May 1, 2016

Maker常用開發板

對於Maker來說,選擇適合的開發板可以加速make的時間。本文會依照難度特色來做分類。


入門款
    Ardunio系列:
  • 基本款(Entry level):Ardunio UNO,Ardunio 101,Ardunio PRO
>>> 特色:pin腳少(少於20隻),PWM port少(不多於6隻),Analog輸入腳位少(少於6)。
>>> 適合入門玩家學習操作I/O(DigitalWrtie),PWM(AnalogWrite),ADC(analogRead)。適合小專案與空間較小之專案。

  • 進階板(Enhanced feature):Ardunio MEGA,Ardunio ZERO,Ardunio DUE
>>> Ardunio MEGA腳位很多,PWM腳多達15隻,對於需要大量馬達或servo的專案來說十分適合,而且其UART多達四組,還有一組SPI和一組I2C可方便擴充。
>>> Ardunio ZERO是小型低電壓板Ardunio。
>>> Ardunio DUE 是ARM-based的Ardunio,腳位很多,同時還有兩個DAC,和USB-OTG,為MEGA板所沒有的。
  • IOT板:Ardunio YUN
>>>Ardunio YUN是一塊同時擁有MCU(Ardunio)和SOC(OS為linux)的開發板,基本連網功能透過linux部份,其餘操作在Ardunio部份上,可支援wifi(IEEE 802.11b/g/n)和ethernet(IEEE 802.11b/g/n),想當然爾,當然是一塊面向物連網的開發板。


  • 其他module
很多,去找吧,我把他們全都放在那了。對於入門者來說,最重要的是有library和API支援,不然自己看datasheet來刻是很困難的。
  • 其他類Ardunio開發板
這裏指得是支援Ardunio語法(library)的開發板,常見的如Picdunio,linkit Smart 7688和linkit 7688 DUO系列等。

進階款
     Raspberry Pi
  • Pi 1,Pi 2 Pi3 , Pi zero:
基本上都是使用Broadcom的單板電腦,都是ARM以處理器為核心,當然ARM系列的優點都有(如省電),支援USB、ethernet、RCA、I2S、SD卡、相機模組。

作業系統有Raspbian(Debian系,論壇資源最多,問題易找到解答)、Arch Linux Arm(Arch linux十分輕量,而且十分先進,其套件管理佳,但難度叫高)、OpenELEC、Pidora(Fedora)等。

使用上需要有linux基礎,而其GPIO操作方式有python與C/C++的方法,其中python較簡單,而C/C++法需要閱讀datasheet才有辦法。

作業系統的優點就是易於擴充,與排程容易,缺點就是操作IO速度容易慢於MCU(但還是有辦法加速的,望向kernel)。

      Banana PI
台灣自行製作,採用中國全志公司的Allwinner A20(ARM Cortex-A7),基本可視為有SATA的Raspberry PI,該有的都有,支援OpenCL。
        Intel 開發板
主要有Intel Galileo和Intel Edison,基於X86,支援Windows,Mac OS X,Linux,為支援度最廣的,功能強大,有網路和USB支援,效能極高,對於運算較大之程式較能負擔(當然不能和PC和Server比啦),板主有看過運用其做Machine Learning和雲端運算操作。

      其他公司開發板推出之開發板
大多數系統廠如技嘉等公司都有推出開發板供顧客使用,這些開發板官方資源通常充足,但缺乏論壇,開發上遇到問題較麻煩。

      MCU(單晶片)
單晶片放在開發板區其實不好,因為你需要自己做開發板,但使用MCU可使你的開發彈性更高。其實Ardunio就是一種由單晶片衍生出的開發板,若要達到更好的程式效率與操作,可透過直接對MCU的暫存器進行操作,程式碼簡潔,但需要閱讀datasheet,所以Ardunio官方提供了一些方法來加速操作,如bitset()和bit()函式之方法。

常見的MCU廠商有:
  • PIC系列的Microchip公司,產品線從8bit到32bit都有,還有dsp和一些模組晶片可使用,其toolchain有免費板且跨平台的(MPLAB X IDE , XC8 ,XC16 ,XC32)。
  • AVR系列的Atmel公司(已被Microchip購併),Ardunio就是使用AVR系列的晶片。也是有免費的free toolchain,同樣也是跨平台。
  • 8051系列:經典的MCU系列由Intel開發,同時由於IP過期,使得現今有許多公司生產,如Microchip、Atmel、STC等。
  • 德州儀器:Msp430系列等。
  • freescale(NXP):Arm Cortex_M系列。
  • 還有很多.....
MCU的產品線多元容易找到適合的晶片。

       SOC(system on chip)

同樣很多產品線,有MIPS架構的,有ARM-A架構的,有X86的,這部份的難度最高,通常要有很多作業系統基礎。


參考資料




libpqxx - postgresql c++ library 基本教學


  • 簡介

libpqxx是postgrsql 官方所推出的函式庫,基本上包裝得很好,用起來十分簡便。
libpqxx官網:http://pqxx.org/


  • linux上安裝方式
請先安裝postgresql,方便起見可安裝php,phppgadmin和apache以利測試。
link:https://wiki.archlinux.org/index.php/PostgreSQL
libray link:http://pqxx.org/download/software/libpqxx/

wget http://pqxx.org/download/software/libpqxx/libpqxx-4.0.tar.gz
tar -zxvf libpqxx-4.0-tar.gz
cd libpqxx-4.0
./configure
make
make install
view raw gistfile1.txt hosted with ❤ by GitHub
arch linux上安裝方式,libpqxx為Extra package。<br /> link:https://www.archlinux.org/packages/extra/i686/libpqxx/
sudo pacman -Sy libpqxx
view raw gistfile1.txt hosted with ❤ by GitHub
安裝完成後,於postgresql安裝目錄下。
cp pg_hba.conf.sample pg_hba.conf
view raw gistfile1.txt hosted with ❤ by GitHub
於pg_hba.conf新增
# IPv4 local connections:
host all all 127.0.0.1/32 md5
view raw gistfile1.txt hosted with ❤ by GitHub
啟動與停止postgresql,基本上使用systemd的linux distro都可用以下方式來處理
sudo systemctl start postgresql.service
sudo systemctl stop postgresql.service
view raw gistfile1.txt hosted with ❤ by GitHub

  • 基本用法
libpqxx通常需要透過pqxx::connection來建立連線,接著以transaction物件pqxx::work執行sql操作。以下為基本範例

#include<iostream>
#include<pqxx/pqxx>
#include<string>
using namespace std;
using namespace pqxx;
int main()
{
string sql;
try{
connection C("dbname=testdb user=postgres password=pqsswd \
hostaddr=127.0.0.1 port=5432");
if (C.is_open()) {
cout << "Opened database successfully: " << C.dbname() << endl;
} else {
cout << "Can't open database" << endl;
return 1;
}
/* Create SQL statement */
sql = "SELECT * FROM USERTEST";
/* Create a transactional object. */
work W(C);
/* Execute SQL query */
pqxx::result r = W.exec( sql );
W.commit();
const int num_rows = r.size();
for (int rownum=0; rownum < num_rows; ++rownum)
{
const pqxx::tuple row = r[rownum];
const int num_cols = row.size();
for (int colnum=0; colnum < num_cols; ++colnum)
{
const pqxx::field field = row[colnum];
std::cout << field.c_str() << '\t';
}
std::cout << std::endl;
}
for (pqxx::result::const_iterator row = r.begin();row != r.end();++row)
{
for (pqxx::tuple::const_iterator field = row->begin();field != row->end();++field)
std::cout << field->c_str() << '\t';
std::cout << std::endl;
}
cout << "table"<<endl;
for (int rownum = 0 ; rownum < num_rows ; rownum++){
cout << r[rownum]["UID"].c_str() << " " << r[rownum]["TRUE_NAME"].c_str() << " " << r[rownum]["GENDER"].c_str()
<< " "<< r[rownum]["NICK_NAME"].c_str() <<endl;
}
C.disconnect ();
}catch (const std::exception &e){
cerr << e.what() << std::endl;
return 1;
}
}
這個範例使用了三種parse資料的方法,分別是使用pqxx::tuple的方式、使用內建iterator的方式與使用類似C++ STL map的key-value方式。
編譯方式:
g++ -o test filename.cpp -lpqxx -lpq
view raw bash hosted with ❤ by GitHub
參考資料:http://www.yiibai.com/html/postgresql/2013/080894.html

精選文章

使用Ardunio Atmega2560 連接 nRF24L01+

使用Ardunio Atmega2560 連接 nRF24L01+ 關於library 目前主流有 https://github.com/maniacbug/RF24 與 https://github.com/TMRh20/RF24 這兩個。 其中TMRh20大大做...