Hi All,
could someone help to explain the access to peripheral registers.
I am little confused.
I worked with DSCs 56F80xx before and the IOCTL commands were simple and straightforward.
I worked with TMS320F2812 and there was also simple peripheral structure access.
For example I need to read DAC0_C0 register.
I am using IAR IDE.
Thanks for help.
Regards
Lukas
Solved! Go to Solution.
Ahh, I think I know what it is then now. Make sure you have the DAC0 clocks turned on. All modules are off by default. So trying to read the register of an off module would give you a fault. Put the following code before any DAC0 register read or wite
//Turn on DAC0
SIM_SCGC2 |= SIM_SCGC2_DAC0_MASK;
Hello Lukas,
All the peripherals of the cortex M4 and so MK60N512VMD100 are momory mapped. The header file first defines the structure of the registers of the particular peripheral as specified in the User Manual. For e.g.\
/*! DAC - Register Layout Typedef */typedef struct { struct { /* offset: 0x0, array step: 0x2 */ __IO uint8_t DATL; /*!< DAC Data Low Register, array offset: 0x0, array step: 0x2 */ __IO uint8_t DATH; /*!< DAC Data High Register, array offset: 0x1, array step: 0x2 */ } DAT[16]; __IO uint8_t SR; /*!< DAC Status Register, offset: 0x20 */ __IO uint8_t C0; /*!< DAC Control Register, offset: 0x21 */ __IO uint8_t C1; /*!< DAC Control Register 1, offset: 0x22 */ __IO uint8_t C2; /*!< DAC Control Register 2, offset: 0x23 */} DAC_Type;
Than there are few helper macros as,
/* ---------------------------------------------------------------------------- -- DAC Register Masks ---------------------------------------------------------------------------- *//*! \addtogroup DAC_Register_Masks DAC Register Masks *//*! \{ *//* DATL Bit Fields */#define DAC_DATL_DATA_MASK 0xFFu#define DAC_DATL_DATA_SHIFT 0#define DAC_DATL_DATA(x) (((uint8_t)(((uint8_t)(x))<<DAC_DATL_DATA_SHIFT))&DAC_DATL_DATA_MASK)/* DATH Bit Fields */#define DAC_DATH_DATA_MASK 0xFu#define DAC_DATH_DATA_SHIFT 0#define DAC_DATH_DATA(x) (((uint8_t)(((uint8_t)(x))<<DAC_DATH_DATA_SHIFT))&DAC_DATH_DATA_MASK)/* SR Bit Fields */#define DAC_SR_DACBFRPBF_MASK 0x1u#define DAC_SR_DACBFRPBF_SHIFT 0#define DAC_SR_DACBFRPTF_MASK 0x2u#define DAC_SR_DACBFRPTF_SHIFT 1#define DAC_SR_DACBFWMF_MASK 0x4u#define DAC_SR_DACBFWMF_SHIFT 2/* C0 Bit Fields */#define DAC_C0_DACBBIEN_MASK 0x1u#define DAC_C0_DACBBIEN_SHIFT 0#define DAC_C0_DACBTIEN_MASK 0x2u#define DAC_C0_DACBTIEN_SHIFT 1#define DAC_C0_DACBWIEN_MASK 0x4u#define DAC_C0_DACBWIEN_SHIFT 2#define DAC_C0_LPEN_MASK 0x8u#define DAC_C0_LPEN_SHIFT 3#define DAC_C0_DACSWTRG_MASK 0x10u#define DAC_C0_DACSWTRG_SHIFT 4#define DAC_C0_DACTRGSEL_MASK 0x20u#define DAC_C0_DACTRGSEL_SHIFT 5#define DAC_C0_DACRFS_MASK 0x40u#define DAC_C0_DACRFS_SHIFT 6#define DAC_C0_DACEN_MASK 0x80u#define DAC_C0_DACEN_SHIFT 7/* C1 Bit Fields */#define DAC_C1_DACBFEN_MASK 0x1u#define DAC_C1_DACBFEN_SHIFT 0#define DAC_C1_DACBFMD_MASK 0x6u#define DAC_C1_DACBFMD_SHIFT 1#define DAC_C1_DACBFMD(x) (((uint8_t)(((uint8_t)(x))<<DAC_C1_DACBFMD_SHIFT))&DAC_C1_DACBFMD_MASK)#define DAC_C1_DACBFWM_MASK 0x18u#define DAC_C1_DACBFWM_SHIFT 3#define DAC_C1_DACBFWM(x) (((uint8_t)(((uint8_t)(x))<<DAC_C1_DACBFWM_SHIFT))&DAC_C1_DACBFWM_MASK)#define DAC_C1_DMAEN_MASK 0x80u#define DAC_C1_DMAEN_SHIFT 7/* C2 Bit Fields */#define DAC_C2_DACBFUP_MASK 0xFu#define DAC_C2_DACBFUP_SHIFT 0#define DAC_C2_DACBFUP(x) (((uint8_t)(((uint8_t)(x))<<DAC_C2_DACBFUP_SHIFT))&DAC_C2_DACBFUP_MASK)#define DAC_C2_DACBFRP_MASK 0xF0u#define DAC_C2_DACBFRP_SHIFT 4#define DAC_C2_DACBFRP(x) (((uint8_t)(((uint8_t)(x))<<DAC_C2_DACBFRP_SHIFT))&DAC_C2_DACBFRP_MASK)
and than there are defines to point to each instance of the peripheral in a memory. The each instance of this peripheral has the structure as defined in register layout above. So the memory pointer is typecasted for the register layout.
/* DAC - Peripheral instance base addresses *//*! Peripheral DAC0 base address */#define DAC0_BASE (0x400CC000u)/*! Peripheral DAC0 base pointer */#define DAC0 ((DAC_Type *)DAC0_BASE)/*! Peripheral DAC1 base address */#define DAC1_BASE (0x400CD000u)/*! Peripheral DAC1 base pointer */#define DAC1 ((DAC_Type *)DAC1_BASE)
so, now if you want to access control register 1 of the DAC0 you can access it as DAC0->C1 and for DAC1 it will be DAC1->C1.
If you want to access the peripherals as you used to access for DSCs 56F80xx etc you have to make your own header file and define register layout accordingly.
This header file design is based on CMSIS standard defined by ARM, this enabled you to make your code portable among family of cortex family. You can get more info on it on ARM Cortex website.
Regards,
d2v0
Hi, many thanks for reply
I dont know how it is possible, but header which I am using looks little different
/*! DAC - Peripheral register structure */typedef struct DAC_MemMap { struct { /* offset: 0x0, array step: 0x2 */ uint8_t DATL; /*!< DAC Data Low Register, array offset: 0x0, array step: 0x2 */ uint8_t DATH; /*!< DAC Data High Register, array offset: 0x1, array step: 0x2 */ } DAT[16]; uint8_t SR; /*!< DAC Status Register, offset: 0x20 */ uint8_t C0; /*!< DAC Control Register, offset: 0x21 */ uint8_t C1; /*!< DAC Control Register 1, offset: 0x22 */ uint8_t C2; /*!< DAC Control Register 2, offset: 0x23 */} volatile *DAC_MemMapPtr;
DAC Register Masks looks identically.
Peripheral instance base addresses isnt identical
/* DAC - Peripheral instance base addresses *//*! Peripheral DAC0 base pointer */#define DAC0_BASE_PTR ((DAC_MemMapPtr)0x400CC000u)/*! Peripheral DAC1 base pointer */#define DAC1_BASE_PTR
when I use this code:
dac_0_status = DAC0_BASE_PTR->C0;
Terminal write message:
default_isr entered on vector 3
I am editing tsi_low_power example.
You would store the value of a register like this:
unsigned char dac_0_status=DAC0_C0;
or to print out:
printf("Value of register is %02X",DAC0_C0);
or to check the status bit LPEN in register DAC0_C0:
if(DAC0_C0 & DAC_C0_LPEN_MASK)
.....
The drivers and other example code projects have several examples of directly using the register values set up by the header files that you can look at. The header file register names also match exactly with what is listed in the documentation, since the header file is created directly from the documentation source.
You should also make sure you have the latest version of the header files, which is part of the Kinetis sample code. It should be Revision 1.0. The header files are at \kinetis-sc\src\cpu\headers
-amh
the newest header file is the version 1.6
** Processor: MK60N512MD100
** Compilers: ARM Compiler
** Freescale C/C++ for Embedded ARM
** GNU ARM C Compiler
** IAR ANSI C/C++ Compiler for ARM
** Reference manual: K60P144M100SF2RM, Rev. 3, 4 Nov 2010
** Version: rev. 1.6, 2011-01-14
jm2c
Thanks for replies,
I take notice that the Keil use little different version of header than IAR.
This thread arisen because this sample of code
dac_0_status=DAC0_C0;
doesnt work poperly (I use IAR), so I thought that I am doing something wrong
when I use this sample of code for copy of DAC0_C0 to variable
the terminal gives me back infinitely a message:
default_isr entered on vector 3
Ahh, I think I know what it is then now. Make sure you have the DAC0 clocks turned on. All modules are off by default. So trying to read the register of an off module would give you a fault. Put the following code before any DAC0 register read or wite
//Turn on DAC0
SIM_SCGC2 |= SIM_SCGC2_DAC0_MASK;
dont forget:
according to your header file, you have to change the code into:
//for CMSIS compliant header file (i.E. keil header file)
SIM->SCGC2 |= SIM_SCGC2_DAC0_MASK;
//for the old one´s
SIM_SCGC2 |= SIM_SCGC2_DAC0_MASK;
thanks for the help
That might change based on the version of the code you are using. The idea with example was to explain how to interpret the file.
Regards,
d2v0