2015年2月28日 星期六

STM32 I/O檢查程式

主要是利用xprintf函式做出一個命令式的I/O讀取及觸發程式。
方便電子設計初期的訊號及功能檢查。
xprintf的設計不錯用。只使用二個I/O函式,所以很容易移植。
利用callback方式,除了連接方便外,也可以中途移轉到另一組通道去。
只要使用xdev_in()及xdev_out()就可以掛載I/O函式了。
程式如下:

#include "xprintf.h"

unsigned short usart6_buf;
unsigned int usart6_rx_cnt =0;
void USART6_IRQHandler(void)
{
    if (USART_GetITStatus(USART6, USART_IT_RXNE) != RESET)
    {
        usart6_buf = USART_ReceiveData(USART6);
        usart6_rx_cnt++;
    }
}

unsigned char usart6_getc(void)
{
    static unsigned int usart6_rx_out = 0;

    /* Wait for Rx FIFO ready */
    while (usart6_rx_out == usart6_rx_cnt) vTaskDelay(1);
    usart6_rx_out++;
    return (usart6_buf & 0xFF);
}

void usart6_putc(unsigned char c)
{
//    while (USART_GetFlagStatus(USART6,USART_FLAG_TXE) == RESET) vTaskDelay(1);
    USART_SendData(USART6, c);
    vTaskDelayMs(1);
}

GPIO_TypeDef * const port[7] =
{
    GPIOA,
    GPIOB,
    GPIOC,
    GPIOD,
    GPIOE,
    GPIOF,
    GPIOG
};
unsigned short const pin[16] =
{
    GPIO_Pin_0,
    GPIO_Pin_1,
    GPIO_Pin_2,
    GPIO_Pin_3,
    GPIO_Pin_4,
    GPIO_Pin_5,
    GPIO_Pin_6,
    GPIO_Pin_7,
    GPIO_Pin_8,
    GPIO_Pin_9,
    GPIO_Pin_10,
    GPIO_Pin_11,
    GPIO_Pin_12,
    GPIO_Pin_13,
    GPIO_Pin_14,
    GPIO_Pin_15
};

char Line[256];                /* Console input buffer */

static void vParser_Task( void *pvParameters )
{
    char *ptr;
    long p1;
    long p2;
    GPIO_TypeDef*  GPIOx;
    unsigned short GPIO_Pin_y;

    (void) pvParameters;
    // set device
    USART6_Config();
    xdev_in(usart6_getc);
    xdev_out(usart6_putc);
    xputs("\nI/O test monitor for STM32F205 evaluation board.\n");
//    xprintf("LFN=%s, CP=%u\n", _USE_LFN ? "Enabled" : "Disabled", _CODE_PAGE);
    for ( ;; )
    {
        xputc('>');
        xgets(Line, sizeof Line);

        ptr = Line;
        switch (*ptr++)
        {
        case '?' :    /* Show Command List */
            xputs(HelpMsg);
            break;

        case 'r' :    // Read Input
            switch (*ptr++)
            {
            case 'a' :    // ra port
                GPIOx = port[0];
                break;
            case 'b' :    // rb port
                GPIOx = port[1];
                break;
            case 'c' :    // rc port
                GPIOx = port[2];
                break;
            case 'd' :    // rd port
                GPIOx = port[3];
                break;
            case 'e' :    // re port
                GPIOx = port[4];
                break;
            case 'f' :    // rf port
                GPIOx = port[5];
                break;
            case 'g' :    // rg port
                GPIOx = port[6];
                break;
            }
            if (!xatoi(&ptr, &p1)) break;
            GPIO_Pin_y = pin[p1];
            GPIO_ReadInputDataBit(GPIOx, GPIO_Pin_y);
            break;
        case 'w' :    // Write Output
            switch (*ptr++)
            {
            case 'a' :    // wa port data
                GPIOx = port[0];
                break;
            case 'b' :    // wb port data
                GPIOx = port[1];
                break;
            case 'c' :    // wc port data
                GPIOx = port[2];
                break;
            case 'd' :    // wd port data
                GPIOx = port[3];
                break;
            case 'e' :    // we port data
                GPIOx = port[4];
                break;
            case 'f' :    // wf port data
                GPIOx = port[5];
                break;
            case 'g' :    // wg port data
                GPIOx = port[6];
                break;
            }
            if (!xatoi(&ptr, &p1)) break;
            if (!xatoi(&ptr, &p2)) break;
            GPIO_Pin_y = pin[p1];
            if ( !p2 )
            {
                GPIO_ResetBits(GPIOx, GPIO_Pin_y);
            }
            else
            {
                GPIO_SetBits(GPIOx, GPIO_Pin_y);
            }
            break;
        }
        vTaskDelayMs(1);
    }
}

void main(void)
{
    void vUSART1_Task( void *pvParameters );

    GPIO_Config();

    xTaskCreate( vParser_Task,   ( signed char * ) "Parser", 512, NULL, tskIDLE_PRIORITY + 1, NULL );

    vTaskStartScheduler();
}

新筆電:GigaByte Q21

此筆電需求是輕、小。
所以從小筆電中找。
找到有雙碟支援,且可以支援8GB記憶體的只有一台=GigaByte Q21。
雙碟是為了安裝SSD所需,又需要HDD容量。
8GB RAM則是要使Win7-64可發揮效能的最低容量。
原始Q21是500G HDD以及2GB RAM,HDD容量還可以,RAM只有一槽,那只有換新了。
所以加購120GB SSD及8GB RAM,然後自己換。
Q21好拆的多,只要卸除背面5顆螺絲就好,沒有隱藏螺絲要找個半天。
再來從電池旁邊開始分開來,慢慢分,到背板全下來。
然後就安裝SSD及8G RAM上去。

再來安裝Win7的工就多了。本來是要保留Win8以SSD安裝Win7做為雙開機系統。
後來發現SSD無法做為開機用(後來發現可以),就安裝EasyBCD做為開機管理。
弄一個不對,Win8掛了(MBR破壞),一切完蛋。

沒想到一切重來竟是新開始。在HDD上重裝Win7,此時發現SSD是可以設定為開機的。
因為BIOS有Secure Boot,在安裝Win7時要取消,使得SSD可以改為開機碟。
但是安裝仍是不行,但還是裝上了Win7在HDD上。後來想了一下,就將HDD先拆掉,只留下SSD。果然可以安裝在SSD上。
在SSD裝好了Win7後再將HDD裝回來,終於完成了Bee想要的配置。不過多了HDD上的Win7,變成可以雙碟開機,那就當成是備用Win7。
接下來是安裝軟體,這個花了不少時間。再加上Win7的一堆升級,升級花了至少十小時。

系統安裝完畢,再來是資料搬家,從PC及NB要搬的檔案一堆,最不好搬的是ISO image檔。
用USB Disk又無法裝單檔大於4GB,除非將USB Disk重新Format成NTFS檔案系統。
用無線連網是沒有檔案大小問題,但傳輸不是很快,又怕干擾到家人使用,就動腦筋到沒有用的Ethernet接頭上。
使用網卡直接對連就可以解決問題,但如何做還是查了不少文。
主要是利用GigaEthernet可以自動換線功能,使用一般網路線就可以對接。
然後人工設定IP,將對方電腦IP設為閘道器。另一台電腦也一樣,然後就可以相互看到。
不過最好設定是工作場所網路,因為Win-XP無法使用家用網路,要從XP上傳資料還是設成工作場所網路。
這樣就解決了大檔案傳輸問題,搬資料也快多了。

弄好了小筆電,就比較一下效能差異,很驚訝的是小筆電效能和大筆電(4年前)的差不了太多。
因為現在CPU型號很多,其實也不好比較,還是找到網站去做比較,好用的是用CPUBoss去比。
可以看出來的確有可能效能差不多。舊筆電CPU是i3,為二核四緒,新筆電是N2930是省電四核。
N2930單一核心比i3的效能少了一半多,但4核總運算量剛好和i3總運算量相近,不過功耗低了很多。

用了一週後,竟發現120GB的SSD已經70%滿了。SSD在快滿時很容易掛掉,所以要找出原因。
做了檔案大小分析,pagefile.sys以及hiberfil.sys佔了很大的量。
pagefile.sys可以用設定虛擬記憶體方式移到HDD去。但hiberfil.sys沒有搬家的方法。
因為hiberfil.sys是休眠用的,以SSD快速開機的能力來說,效果差不多,就直接取消。
找到取消的方法,要用人工下命令的方式。
以系統管理員的身份叫用命令列,然後打powercfg -h off。然後重開機就沒有hiberfil.sys檔了。
但是做了SSD還是近65%滿,分析使用檔案大小只有30G,但使用了66G。
做了磁碟清理,磁碟重排也沒有用。
後來在磁碟清理中找到刪除還原點資料,一執行,釋放了30G以上的空間,系統使用空間降到32GB。
還原點的資料還無法看到,難怪不管分析檔案空間如何分析都不對,原來是還原點備份造成的。