R8应用摘记

1. 变量,内存,存储空间 

Resase RAM 

AUTO变量只是动态分配存储空间而已,硬件不帮你做清零的事

所以,局部变量需要自己做清零处理。

仿真时,不要用看门狗,否则设置断点时CPU一直复位。

所以仿真时要对程序进行修改,#ifdefine 或者 #if

3问题:

当基于瑞萨 M16C, R8C 系列微控制器进行C 语言应用程序设计时,如果在子函数中定义的变量超过255 个字节,程序编译出错。

分析:

针对这种情况,问题的主要原因是子函数中定义的变量在函数调用时都是保存在堆栈中,而NC30 编译器默认设置的在函数调用时使用的堆栈大上限为255 个字节,因此, 当子函数中定义超过255 个字节的变量时,编译会出错。

解决:

基于上述分析,我们只需要对 NC30 编译器默认设置的函数调用时使用的堆栈上限修改即可,具体做法如下:

1, 在 HEW workspace 的菜单栏鼠标左键点击“Build”,然后选择“Renesas M16C

Standard Toolchain…”进入Toolchain 设定菜单;

2,选择“C”设定菜单,下拉“Category”选择列表,然后选择“Code Modification”,此时,在下面的“Miscellaneous Option”窗口里可以看到“[-AO2]”选项,在前面购选次选项即可。

 针对 64k 以外地址空间const 类型数组的访问处理如下(对指向数组指针进行far类型声明):

 ///just add far at the array address in the function parameter.

 5.

 在定义对应变量的时候用volatile 类型定义,可以避免编译调试设置断点时地址丢失 

R8C 如何混合编程

初略的总结有三种方式:

1. 行汇编方式,使用关键字 asm(“汇编命令”), 在 C 程序中嵌入汇编程序如

Void cal(void)

{

asm (“bset start_bit”);

….

}

2. 使用#pragma ASM 和#pragma ASMEND 格式, 整段嵌入汇编程序, 如:

#pragma ASM

FSETI

nop

beset start_bit

#pragma ASMEND

3. 使用#pragma PARAMETER 定义带参数的汇编函数

  • 在声明 #pragma PARAMETER 之前编写汇编函数的原型声明。同时也必

须声明参数类型。

  • 2. 在汇编函数的参数列表中通过 #pragma PARAMETER 声明所使用的寄

存器的名称。

  • 例如:

extern unsigned int asm_func(unsigned int, unsigned int);

#pragma PARAMETER asm_func(R0, R1) 

#pragma

 R8C/M16C提供一系列预处理指令,能够很好的优化C代码。 

本文以nc30编译器为例,谈谈#pragma的用法。 

 1)。与内存有关的命令 

#pragma ROM 

将一个变量放入ROM里面,比如: 

#pragma ROM aa 

int aa; 

 #pragma BIT 

位变量申明。表示将一个变量放在能够进行位操作指令的地址区,比如: 

#pragma BIT aa; 

struct _aa{ 

  char bit0:1; 

  char bit: 7; 

}aa; 

aa.bit0 = 1; 

 #pragma SBDATA 

申明访问变量是基于SB寄存器寻址的方式,如: 

#pragma SBDATA aa; 

int aa; 

访问aa时,是基于SB寄存器寻址的 

 #pragma SECTION 

将程序或变量什么在某个区域 

 #pragma STRUCT 

结构体对齐申明 

#pragma STRUCT _aa unpacked 

struct _aa{ 

  int aa; 

  char bb; 

}; 

表示结构体_aa不对齐 

 #pragma EXT4MPTR 

表示将变量申明在大于4MB的区域 

#pragma EXT4MPTR  aa 

int _far aa; 

 2),针对目标平台的预处理指令 

#pragma ADDRESS 

绝对地址申明,将变量放入某个绝对地址,例如 

#pragma ADDRESS aa 0xff000 

int aa; 

 #pragma BITADDRESS 

位绝对地址申明。典型应用是申明一个bool变量到某个绝对地址 

#pragma BITADDRESS aa 0 0xff000 

_Bool aa; 

 #pragma INTCALL 

申明一个软中断(int指令)函数 

#pragma INTCALL 25 func() 

void main(void) 

  func(); 

执行func()时,相当于执行int 25指令 

 #pragma INTERRUPT 

这个就不多说了,申明一个中断服务子函数 

#pragma INTERRUPT isr1(vect = 20) 

void isr1(void); 

 #pragma PARAMETER 

申明通过寄存器传递参数到汇编函数 

int asm_func(int, int); 

#pragma PARAMETER asm_func(R0,R1) 

void main(void) 

  int i,j; 

  asm_func(i,j); 

表示i,j参数通过寄存器R0,R1传递到汇编函数asm_func(); 

 3),汇编预处理指令 

#pragma ASM 

#pragma ENDASM 

内嵌汇编指令,例如: 

void fun(void) 

#pragma ASM 

  fset i 

 nop 

#pragma ENDASM 

#pragma JSRA 

申明调用一个函数时,使用JSR.A指令 

extern void func(); 

#pragma JSRA func 

void main(void) 

  func(); 

}  

#pragma JSRW 

类似于#pragma JSRA 

后记: 

还有基于M16C系列RTOS的预处理指令,例如 

#pragma TASK tsk1 

void tsk1(void) 

表示申明tsk1为一个任务(线程)。 

等等。

3 section R8 flash handling

void block_erase(  unsigned char *ers_addr)
 {
    di();                         //禁止中断
    fmr0=0x01;             
    asm("");
    fmr0=0x03;
    asm("");
    fmr1=0x80;
    asm("");
    fmr1=0x82;                     //使用EW1模式
    asm("");
    *ers_addr=0x20;               //擦除命令,先写0X20,再写0XD0
    *ers_addr=0xd0;               //擦除命令
    while(!fmr00);               //等待擦除完成
    if(fmr07==1) *ers_addr=0x50; //清除状态寄存器
    fmr0=0x01;
    ei();
 }
void writedata(unsigned char *ers_addr,unsigned char wdata)
 {
    di();                 //禁止中断
    fmr0=0x01;
    asm("");
    fmr0=0x03;
    asm("");
    fmr1=0x80;
    asm("");
    fmr1=0x82;
    asm("");
    *ers_addr=0x40;              //命令 选写0X40  再写数据
    *ers_addr=wdata;             //数据
    while(!fmr00);               //等待擦除完成
    if(fmr07==1) *ers_addr=0x50; //清除状态寄存器
    fmr0=0x01;
    ei();
 }
调用:
block_erase((void *)0x2400); 
 block_erase((void *)0x2800);
writedata((void *)Ftpd,Ubuf[Dtmp2]);

Ftpd--是一个变量,Ubuf[Dtmp2]  是一个变量数组。
FLASH写,只能把1变成0,不能把01

是内部的块,但是如果上面的函数所在的块是不能操作的,如果是函数在块0哪么只能对块1操作与AB块操作。

 R8C\Tiny 单片机的DataFlash处理起来比较繁琐,处理模式分为EW0模式和EW1模式,通常我们采用EW1模式。  在此模式中,DataFlash的一个块擦除时间比较长,经常达到100ms以上,这个时间远远超出了WDT的时间,所以在擦除DataFlash时,如果处理不当,会导致单片机的死机。

  在擦除DataFlash时,主程序已经停止,在等待擦除DataFlash时结束,此时不可能在主程序中喂狗;在R8C\Tiny 单片机,当WDT开启之后,程序将不能关闭WDT
  综合以上的特点,要处理擦除DataFlash时的WDT溢出问题,处理方法如下:
  1、开启擦除挂起
  2WDT设置成中断模式,普通模式
  3、执行擦除命令
  4、擦除中,WDT溢出中断,可以忽略或者喂狗,判断状态软件复位 

4. section 4 

4.1 sec30.inc

 我们知道,编译器在编译程序的时候,会将程序按照一定的方式来预处理,编译,链接和重定位。

R8C/M16C使用的是nc30系列编译器,这个编译器被集成到HEW里。当我们使用HEW来调试时R8C/M16C芯片时,会调用NC30来编译,链接等工作,最后生成一些可执行文件,包括仿真文件.x30和可执行的二进制文件.mot

 下面讲的是NC30的内存分配,也就是我们在程序里经常看到的section关键字。

当我们新建一个R8C的汇编工程后,可以在sect30.inc看到整个代码的内存分配。

NC30的内存分配如下:

SBDATA  SBDATA

near RAM 低地址RAM

far RAM 高地址RAM

near ROM 低地址ROM

far ROM 高地址ROM

stack 

heap 

Initial data of "data" section 初始化了的数据区

switch table section 跳转表

code 代码区

variable vector section  可变的向量区

fixed vector section 固定的向量区

 我们分别讲讲他们的含义。

SBDATA

这个区域从内部RAM的起始地址开始,一般用来存放经常使用的数据,比如volatile变量等,这样可以提高程序执行速度

使用#pragma SBDATA指令,告诉编译器将变量重定位到SBDATA区域。比如:

#pragma SBDATA cc

int cc;

near RAM

低地址RAM区。利用关键字_near或者__near可以将变量申明到此区域,比如:

int _near cc;

Stack

Heap

near ROM

低地址ROM区,存放常量

far RAM

高地址RAM区,一般用来扩展外部RAM

far ROM

高地址ROM区,存放常量等

Initial data of 'data' section

初始化数据段,位于ROM里面都是初始化好了的数据

switch table section

跳转表

code

代码区,存放二进制可执行代码

 variable vector section

可变的向量区,存放中断向量

fixed vector section 

固定的向量区,存放系统异常向量,例如复位,断点等

 提示:

在HEW的build--toolchain里面,可以选择一些编译或链接参数等。 

4.2   date flash table. 

From <<R8C25 Group Data Flash Table>>

 Section configuration managed by NC30

 data:  stores static variables with initial values.

bss:  stores static variables without initial values.

rom :   stores character strings and constants

program: stroes programs

vector:  variable vector area ( not generated by compiler)

fvector:  fixed vector area( not generated by compiler)

stack:  stack area ( not generated by compiler)

heap:    heap area( not generated by compiler) 

3.4 Controlling Memory Mapping of Structs

When mapping structs, NC30 packs them in the order they are declared to minimize the amount of memory used.

However, if the processing speed has priority, write a statement “#pragma STRUCT” to control the method of mapping structs into memory.

This section explains the extended functions used for mapping structs into memory.

1. (#pragma STRUCT tag name unpack)

This command statement inserts pads into a struct so that its total size of struct members is adjusted to even bytes.

This statement is specified when the access speed has priority.

2. (#pragma STRUCT tag name arrange

This command statement maps even-size members before other members regardless of the order they are decleared.

If this statement is used in combination with the last one,  each even-size member is mapped into memory from an even address, thus allow efficient memory access.

5. section 5   date types and variables

Date types

Integer constants:   decimal : 12;  hexadecimal :0x3b or 0X3B;  octal :  07;// mumerals are preceded by 0;

Real Constants (Floating-Point Constants)

Floating-point constants refer to signed real numbers that are expressed in decimal. These

numbers can be written by usual method of writing using the decimal point or by

exponential notation using "e" or "E".

• Usual method of writing Example: 175.5, -0.007

• Exponential notation Example: 1.755e2, -7.0E-3

1.2.2 Variables 

Real datetype:

1. float : 32bits   number of significant digits: 9 

2. double : 64bits

3. long double: 64 bits.

原文地址:https://www.cnblogs.com/aprilapril/p/2961656.html