Keil Logo

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 Name Address Description
CAN_CTL_STAT 0xEF00 Control/Status Register
CAN_INTID 0xEF02 Interrupt Register
CAN_BIT_TIMING 0xEF04 Bit-Timing Register
CAN_MASK_SHORT 0xEF06 Global Mask Short
CAN_UMASK_LONG 0xEF08 Upper Global Mask Long
CAN_LMASK_LONG 0xEF0A Lower Global Mask Long
CAN_UMASK_LAST 0xEF0C Upper Mask of Last Message
CAN_LMASK_LAST 0xEF0E Lower Mask of Last Message
CAN_OBJ[15] 0xEF10 Message 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;
}
  Arm logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.

Change Settings

Privacy Policy Update

Arm’s Privacy Policy has been updated. By continuing to use our site, you consent to Arm’s Privacy Policy. Please review our Privacy Policy to learn more about our collection, use and transfers
of your data.