Keil™, An ARM® Company

C166 User's Guide

XBUS Peripherals

XBUS peripherals are located in sdata memory. However, the memory they occupy may not be used as general purpose RAM. To use an XBUS peripheral you must allocate the memory with the RESERVE linker directive. You must also declare XBUS peripheral objects with the volatile keyword to prevent the compiler from optimizing XBUS peripheral accesses.

The following example shows how on-chip peripherals located in XRAM are accessed by the compiler.

stmt level    source
   1          /* Synchronous Serial Port (SSP), connected via XBUS */
   2          #define SSPCON0  (*((unsigned int volatile sdata *)  0xEF00))
   3
   4
   5          unsigned int test (void)  {
   6   1        SSPCON0 = 0x0004;
   7   1        while (SSPCON0 & 0x8000);   /* wait */
   8   1        return (SSPCON0);
   9   1      }
ASSEMBLY LISTING OF GENERATED OBJECT CODE
             ; FUNCTION test (BEGIN  RMASK = @0x4010)
                                           ; SOURCE LINE # 5
                                           ; SOURCE LINE # 6
0000 E044          MOV     R4,#04H
0002 F6F400EF      MOV     0EF00H,R4
                                           ; SOURCE LINE # 7
0006         ?C0001:
0006 F2F400EF      MOV     R4,0EF00H
000A 66F40080      AND     R4,#08000H
000E 3DFB          JMPR    cc_NZ,?C0001
0010         ?C0002:
                                           ; SOURCE LINE # 8
0010 F2F400EF      MOV     R4,0EF00H
                                           ; SOURCE LINE # 9
0014 CB00          RET
             ; FUNCTION test (END    RMASK = @0x4010)

Using XBUS CAN Registers

The CAN controller, integrated into some C167x derivatives, is an XBUS peripheral. The C166 Compiler provides a header file (CAN167.H) that defines all the CAN-related registers (in sdata memory) and several status information masks.

SFR NameAddressDescription
CAN_CTL_STAT0xEF00Control/Status Register
CAN_INTID0xEF02Interrupt Register
CAN_BIT_TIMING0xEF04Bit-Timing Register
CAN_MASK_SHORT0xEF06Global Mask Short
CAN_UMASK_LONG0xEF08Upper Global Mask Long
CAN_LMASK_LONG0xEF0ALower Global Mask Long
CAN_UMASK_LAST0xEF0CUpper Mask of Last Message
CAN_LMASK_LAST0xEF0ELower Mask of Last Message
CAN_OBJ[15]0xEF10Message Object: Each of the 15 possible message objects uses 16 bytes defined by the can_obj structure.
/* Structure for a single CAN message object */
/* A total of 15 such object structures exists (starting at EF10H) */
struct can_obj {
  unsigned int  msg_ctl;   /* Message Control       */
  unsigned long arbitr;    /* Arbitration           */
  unsigned char msg_cfg;   /* Message Configuration */
  unsigned char msg[8];    /* Message Data 0-7      */
  unsigned char dummy;     /* Reserved Byte         */
};

The following program example shows how to use the CAN message object to setup various CAN registers.

#include <can167.h>

void test_can (void)  {
  /* init CAN controller */
  CAN_CTL_STAT = 1;
  /* init arbitration register for object 0 */
  CAN_OBJ[0].arbitr = 0xE0000000L;
  /* write to message buffer for object 0 */
  CAN_OBJ[0].msg[0] = 0;
  CAN_OBJ[0].msg[1] = 1;
  CAN_OBJ[0].msg[2] = 2;
  /* write to message configuration for object 0 */
  CAN_OBJ[0].msg_cfg = 0x38;

  /* init arbitration register for object 1 */
  CAN_OBJ[1].arbitr = 0xE0010000L;
}