顯示具有 嵌入式系統 標籤的文章。 顯示所有文章
顯示具有 嵌入式系統 標籤的文章。 顯示所有文章

2022年9月9日 星期五

[MCU開發]解決S32K編譯時發生VMA error

 Description Resource Path Location Type Ld error: section .stack VMA [20002c00,20002fff] overlaps section .heap VMA Meter_AS_MCU C/C++ Problem

"c:/nxp/s32ds_arm_v2.2/s32ds/build_tools/gcc_v6.3/gcc-6.3-arm32-eabi/bin/../lib/gcc/arm-none-eabi/6.3.1/../../../../arm-none-eabi/bin/real-ld.exe: section .stack VMA [20002d00,20002fff] overlaps section .heap VMA [20002a58,20002d57]"

這問題描述主要說的是./stack跟heap去重疊到

導致編譯錯誤


解法如下 : 

開啟S32 Design Studio 開啟專案的Project Settings->Linker files

點選S32K1xx_32_ram.ld


HEAP_SIZE  = DEFINED(__heap_size__)  ? __heap_size__  : 0x00000400;

STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x00000400;

並在以下資料夾入前綴 : __attribute__ ((section(".data"))) 如下 : 

 __attribute__ ((section(".data")))m_interrupts          (RX)  : ORIGIN = 0x1FFFC000, LENGTH = 0x00000400

  __attribute__ ((section(".data")))m_text                (RX)  : ORIGIN = 0x1FFFC400, LENGTH = 0x00003C00

  /* SRAM_U */

  __attribute__ ((section(".data")))m_data                (RW)  : ORIGIN = 0x20000000, LENGTH = 0x00003000

接著在S32K1xx_32_flash.ld

動態調整heap size跟stack size 如下 : 

HEAP_SIZE  = DEFINED(__heap_size__)  ? __heap_size__  : 0x00000300;

STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x00000300;

即可解決

另一種暴力的方式如下 : 

#define VAR_PUT_IN_DATA_SECTION    __attribute__((section(".data")))

2022年8月24日 星期三

[嵌入式系統]開機的順序與記憶體的跳換

開機的順序為bootloader->u-boot

bootloader 可以想像成是PC開機到windows前的GRUB開機管理程式

ARM 結構的 CPU 會從位址 0x00000000 開始執行

但是bootloader是更底層

Bootloader會針對SoC的clock rate做初始化 以及Ram的初始化

透過memory map執行跳躍到u-boot區段

其中記錄開機後bootloader載入的區段,接著u-boot 是linux提前載入的程式階段在此階段會存在很多小工具讓使用診進行診斷或使用 - busybox。

其主要程式為Start.s,分為boot loading模式及下載模式,下載模式可使用一些指令下載,如xmodem, tftp, usb等 並將其存至Ram或Flash固存中。其中透過調用lowlevel_init.S的lowlevel_init進行u-boot相關的低階初始化。

接著跳轉到kernel 這段就是linux的核心層 也就是linux最基礎的功能包含driver的環境


kernel層完之後會根據參照及傳遞值跳躍到application層。


一但到application層即代表 已經開至Userspace上層

2021年4月6日 星期二

[C語言韌體]微控制器(MCU)開發雜記








C語言在MCU的開發上使用while迴圈去進行大循環
常見會有while(1){...}的用法
有時候也會出現for( ; ; ) {...}的用法 跟while(1)是一樣的


20210506 更新 do{ ... }while(0)的妙用
do                                                                                             
{                                                                                              
        code statement                                                              
} while (0)

今天在看nRF52-DK 的code時看到官方定義的code出現此環節,一般來說,mcu會以上述while(1) 或for( ; ; ) 來進行無限迴圈的應用,以do{...}while(0)的定義並不是要做無窮迴圈應用為何還是這樣使用呢? 本來以為是coding style習慣問題,在參考完下述連結後,有更多此妙用的介紹。

好處是必執行外,不需要多餘的if else壟餘code 也避免goto的危險性








使用Trace32 debug
 
 





















 












 
 
 















因葦
k
ll
lll
 
 
 

2017年11月11日 星期六

[嵌入式系統] BT module 透過 UART的溝通

[BLE protocol]


[BT programming]
[BT programming developer kit]
BT programming在TI的CC2640/CC2650系列來說若要在PC端programming可以找到很多資料不是太大的難題
但若要在Linux底下programming,除非原廠的協助,否則很難找到相關文獻
好在原廠有提供一些幫忙,在CC26xx系列與CC13XX系列的Bootloader的位置是一樣的所以我們可以沿用。
原廠文獻參考:
一開始先是透過相同問題找到這篇 : CC2640R2F: sbl code on Linux點選下方提供的網址來到 : Running the Example Applications
並找到了開發工具的網址 : TI 15.4-Stack Gateway Linux Software Development Kit












Buy from Texas Instruments or Third Party 欄位選擇Get Software按鈕可以進到下面頁面
http://www.ti.com/tool/download/TI-15-4-STACK-GATEWAY-LINUX-SDK




[BT programming debugging]
Strace是一個很好用的工具S代表的是system,主要就是可以透過系統的載入程式來偵錯,看程式的flow。
在嵌入式系統中是透過在Buildroot底下輸入make menuconfig去裝起來,
我們可以在


有關Strace的文章網路很多我們可以參考 :  參考


以下圖


strace -xxf -T -eread=3 -ewrite=3 ./host_cc13xx-sbl /dev/ttySP1 R13.bin -e -p -v > 123.log
-T代表的是印出每一行間隔的時間






[BT pass throught]






















































參考官網教學:poll


#include <stdio.h>
#include <unistd.h>


#include <sys/poll.h>  //首先include




struct pollfd fds[2];//宣告大小為2的fds結構體

fds[0].fd = fd;//將一已宣告之file node assign給fds結構體
fds[0].events = POLLIN;//宣告等待poll的事件類型為輸入

fds[1].fd = bt_fd;
fds[1].events = POLLIN;



ret = poll(fds, 2, 5000);//time out 5000ms(5s)
if(ret == -1)

{
    perror("poll error");
return 1;
}
if(!ret)
{
    printf("5 seconds elapsed.\n");
return 0;
}

if(fds[0].revents & POLLIN)
{
printf("fds[0] can read\n");//設定fds[0]有事件進來時的處理應對策略
}
if(fds[1].revents & POLLIN)
{
    printf("fds[1] can read\n");
}
return 0;


由於pass throught的
資料在一般模式下會視為char轉換為Hex,以本案例來說BT lightpoint's data pass throught需要原始的資料
因此我們需要將uart宣告為raw => 在Linux programming時有現成的function可以使用

cfmakeraw => 參考

在使用時須要#include
void cfmakeraw(struct termios *termios_p);

解決方法如下 :
int res;
    struct termios new_tio;
    bt_fd = open(BT_DEVICE_UART, O_RDWR|O_NOCTTY|O_NDELAY);
    if (bt_fd < 0)
    {
        printf("BT_HCI open tty node failed !\n");
        return bt_fd;
    }
    else
    {
        printf("BT_HCI open tty node success !\n");
    }
    bzero(&new_tio,sizeof(new_tio));
    new_tio.c_cflag |= (B115200|CS8|CLOCAL|CREAD);
    new_tio.c_cflag &= ~(PARENB|CSTOPB);
    new_tio.c_lflag &= ~(ECHO|ECHOE|ICANON|ISIG);
    new_tio.c_oflag &= ~OPOST;
    new_tio.c_iflag &= ~(INLCR|ICRNL);
    new_tio.c_cc[VMIN] = 0;
    new_tio.c_cc[VTIME] = 10;
    res = tcflush(bt_fd, TCIFLUSH);
    cfmakeraw(&new_tio);
    if (res < 0)
    {
        printf("BT_HCI tcflush failed !\n");
        return res;
    }
    else
    {
        printf("BT_HCI tcflush success !\n");
    }
    res = tcsetattr(bt_fd, TCSANOW, &new_tio);
    if (res < 0)
    {
        printf("BT_HCI tcsetattr failed !\n");
        return res;
    }
    else
    {
        printf("BT_HCI tcsetattr success !\n");
    }
    printf("HCI_serial_init success!!");
    return bt_fd;
}









2017年10月15日 星期日

[嵌入式系統]Ch7-3 Linux驅動程式 模板與實作(以TP module為例)

TP module, TP指的是touch pad(觸控板)
有別於一般的driver是output device,Touch pad module是input device
實做起來也會有所不同,




Specifying tslib for DirectFB touchscreen input driver
提到的
export TSLIB_TSDEVICE=/dev/input/touchscreen0
export TSLIB_CONFFILE=/etc/ts.conf
export TSLIB_PLUGINDIR=/usr/lib/ts
export TSLIB_CALIBFILE=/etc/pointercal

我們知道原來tp module的報點api是引用directfb底下的api 我們需要註冊tslib_device
註冊點以NXP(freescale)iMx系列來說是在骨架/etc的init.d底下的rcS:

iMx/buildroot/fs/skeleton/etc/init.d/rsS
我們可以透過debug uart拉出來的訊息
來進行debug => 透過cat TP module的device node去確定正確的device node並註冊給linux kernel

2017年8月12日 星期六

[嵌入式C] MCU

MCU筆記

2017/8/12 更新:


microproccesser bus rate = Oscillator / 2 


int main()
{
  LOCK();   //disable irq

  init_periphery(); //initialize.c 
     ->Step1.Set up elpi mode (clock)
     ->Step2.Setup GPIO 
     ->Step3.Setup lp timer  
     ->Step4.Setup I2C
     ->Step5.
          /* switch to very low power run mode */
            set_vlpr_mode();
            /* switch to very low power stop mode */
            set_vlps_mode();
configure_NVIC(); //initialize.c
     ->Step0.設定&註冊 irq 優先權

init_app_objects(); //initialize.c
     ->Step1. initialize button press dispatcher */
     ->Step2.initialize state object */
  
init_watchdog(); //initialize.c

  UNLOCK();  //enable irq


  while(true)
  {
    set_vlps_mode();

    const sEvent * evt = GetEvent(&_BtnObj.base.EvQueue);
    if(evt != 0) {
      /* dispatch event to btn object */
      SMDispatch((sSM*) &_BtnObj, evt);
    }

    evt = GetEvent(&_StateObj.base.EvQueue);
    if(evt != 0) {
      /* dispatch event to state object */
      SMDispatch((sSM*) &_StateObj, evt);
    }

    /* feed the watchdog */
    COP_DRV_Refresh(0);
  }

  return 0;
}




2017年7月24日 星期一

[嵌入式系統] Linux Signal信號一覽

SIGHUP 1 A 終端掛起或者控制進程終止

SIGINT 2 A 鍵盤中斷(如break鍵被按下)

SIGQUIT 3 C 鍵盤的退出鍵被按下

SIGILL 4 C 非法指令

SIGABRT 6 C 由abort(3)發出的退出指令

SIGFPE 8 C 浮點異常

SIGKILL 9 AEF Kill信號

SIGSEGV 11 C 無效的內存引用

SIGPIPE 13 A 管道破裂: 寫一個沒有讀埠的管道

SIGALRM 14 A 由alarm(2)發出的信號

SIGTERM 15 A 終止信號

SIGUSR1 30,10,16 A 用戶自定義信號1

SIGUSR2 31,12,17 A 用戶自定義信號2

SIGCHLD 20,17,18 B 子進程結束信號

SIGCONT 19,18,25 進程繼續(曾被停止的進程)

SIGSTOP 17,19,23 DEF 終止進程

SIGTSTP 18,20,24 D 控制終端(tty)上按下停止鍵

SIGTTIN 21,21,26 D 後台進程企圖從控制終端讀

SIGTTOU 22,22,27 D 後台進程企圖從控制終端寫
原文網址:https://read01.com/zP6eGR.html