Luminary Cortex-M3 and Keil IDE

Discussion in 'Embedded Systems and Microcontrollers' started by millwood, Jul 14, 2009.

  1. millwood

    Thread Starter Guest

    I am moving gradually to the new ARMv7M variant, and specifically the Luminary chips. I have a dev board in the mail to me (LM3S811, $49 for the board, with a OLED display and can function like a jtag adapter should I move onto something else).

    I had played with LPCs before but those Luminary beasts are totally different in how they are setting up, and sample code is hard to come by.

    so it took me an entire morning to get something going.

    Code ( (Unknown Language)):
    1.  
    2. #include <lm3s811.h>
    3.  
    4. #define PORTA_ENABLED   0x01
    5. #define PORTB_ENABLED   0x02
    6. #define PORTC_ENABLED   0x04
    7. #define PORTD_ENABLED   0x08
    8. #define PORTE_ENABLED   0x0f
    9.  
    10. //hardware configuration
    11. #define LED1    GPIO_PORTA_DATA_R                   //1st led string on porta
    12. #define LED2    GPIO_PORTC_DATA_R                   //2nd led string on partc
    13. #define LED3    GPIO_PORTD_DATA_R                   //2nd led string on partd
    14.  
    15. void init_mcu(void) {
    16.  
    17.     SYSCTL_RCGC2_R=PORTA_ENABLED | PORTC_ENABLED | PORTD_ENABLED;   //enable gate a, c and d;
    18.  
    19. //set up porta
    20.     GPIO_PORTA_DIR_R=0x0f;                          //lowest four bits for output
    21.     GPIO_PORTA_DEN_R=0x0f;                          //lowest four bits enabled for digital
    22.     GPIO_PORTA_AFSEL_R=0x00;                        //no alternative functions on all 8 bits
    23.     GPIO_PORTA_DATA_R=0x55;                         //output set to 0b01010101. But only last four bits used due to DIR_R setting
    24.  
    25. //set up portc
    26.     GPIO_PORTC_DIR_R=0xff;                          //all 8 bits for output
    27.     GPIO_PORTC_DEN_R=0xff;                          //all 8 bits enabled for digital
    28.     GPIO_PORTC_AFSEL_R=0x00;                        //no alternative functions on all 8 bits
    29.     GPIO_PORTC_DATA_R=0x01;                         //output set to 0b00000001. But only last four bits used due to DIR_R setting
    30.  
    31. //set up portd
    32.     GPIO_PORTD_DIR_R=0xff;                          //all 8 bits for output
    33.     GPIO_PORTD_DEN_R=0xff;                          //all 8 bits enabled for digital
    34.     GPIO_PORTD_AFSEL_R=0x00;                        //no alternative functions on all 8 bits
    35.     GPIO_PORTD_DATA_R=0x01;                         //output set to 0b00000001. But only last four bits used due to DIR_R setting
    36.  
    37. }
    38.  
    39. void delay(int dly) {
    40.     for (; dly>0; dly--)
    41.         ;
    42. }
    43.  
    44. int main(void) {
    45.    
    46.     int LED2_i=1;
    47.     int LED3_i=1;
    48.    
    49.     init_mcu();
    50.     while (1) {
    51.         delay(5000);
    52.         LED1=~LED1;                                 //blinking led1
    53.        
    54.         LED2=LED2_i;
    55.         if (LED2_i==0x80)                           //if the left most bit is on
    56.             LED2_i=1;                               //reset to to the right most bit
    57.         else
    58.             LED2_i<<=1;                             //otherwise, shift to the left by 1 bit
    59.  
    60.         LED3=LED3_i;
    61.         if (LED3_i==0xff)                           //if all leds are on
    62.             LED3_i=0;                               //turn all LEDs off
    63.         else
    64.             LED3_i=LED3_i+1;                        //increment by 1;
    65.     }
    66.  
    67. }
    68.  
    it is a way to blink 3 strings of LEDs on port A, port C and port D:

    on port A, we are just blinking the last four leds:
    on port C, we are rolling leds from the lowest bit to the highest bit.
    on port D, we are just incrementing the leds, linearly.

    the weird thing about those luminary chips is the rcgc registers. in particular, we have to run the clocks to the ports before we can use them. that took me a while to figure out, :).

    so here it is. if someone is using the luminary chips, you don't have to waste a morning to figure that out.
     
  2. millwood

    Thread Starter Guest

    I use hi-tide as my IDE on PIC. it is a great improvement over the command lines, but not that great for debugging purposes.

    Keil's IDE, uvision, has many interesting features. the ones I like the most are:

    1) logic analyzers: it shows up, in very graphics fashion, the values of the variables, or registers, and you can lay them out and see how they change vs. one another. Here, you can see that how PortD is incrementing it linearly.

    2) peripheral: you can pull up any peripherals and see its pin / registers status. here, you can see how the pins for port A, C and D change.
     
  3. millwood

    Thread Starter Guest

    and if you zoom in in the logic analyzer, you can see how the variables / pins change from one clock to another.

    features like those really helped debugging a program.

    it just gave me one more reason to stay in the arm land.
     
  4. millwood

    Thread Starter Guest

    finally, I was able to get the adc working, both directly through the registers and then through Luminary's StellarisWare.

    if you think PIC's adc is @#$ked up, take a look at the following code to see how a simple pulling of adc is done on the Luminary chip, :(.

    Code ( (Unknown Language)):
    1.  
    2. #include <lm3s811.h>
    3.  
    4. int ulSensor0Data, ulSensor1Data, ulSensor2Data;
    5.  
    6. void init_mcu(void) {
    7.    
    8.     SYSCTL_RCGC0_R |= (SYSCTL_RCGC0_ADC |                   //turn on adc
    9.                         SYSCTL_RCGC0_ADCSPD500K);           //and run it at 125ksps
    10.     ADC_ACTSS_R &= ~(ADC_ACTSS_ASEN0 | ADC_ACTSS_ASEN1 |
    11.                     ADC_ACTSS_ASEN2 | ADC_ACTSS_ASEN3);     //programming adc: disable ADCACTSS during reprogramming
    12.     ADC_SSPRI_R = (ADC_SSPRI_SS3_1ST | ADC_SSPRI_SS1_2ND |
    13.                     ADC_SSPRI_SS0_3RD | ADC_SSPRI_SS2_4TH); //set up the priority: SS3 first, SS1 2nd, SS0 3rd and SS2 4th
    14.    
    15.     ADC_EMUX_R = (ADC_EMUX_EM1_PROCESSOR);                  //set up the sequency trigger: ss1 by processor only in this example
    16.    
    17.     //set-up sequence 1                                     //only sequence 1 is used. can have up to 4 steps
    18.     ADC_SSMUX1_R = ((0 << ADC_SSMUX1_MUX0_S) |              //step 0 from adc0
    19.                     (1 << ADC_SSMUX1_MUX2_S) |              //step 1 from adc2
    20.                     (2 << ADC_SSMUX1_MUX1_S));              //step 2 from adc1
    21.     ADC_SSCTL1_R =                                          //step 0: single-ended, no temp sensor, no interrupt;
    22.                                                             //step 1: single-ended, no temp sensor, no interrupt;
    23.                     (ADC_SSCTL1_IE2 | ADC_SSCTL1_END2);     //step 2: single-ended, no temp sensor, interrupt enabled;
    24.     //may configure addtional sequences from here.
    25.  
    26.     //ADC_SAC_R = ADC_SAC_AVG_2X;                               //hardware averaging 2x. 0 - 64x oversampling available
    27.     ADC_ACTSS_R |= ADC_ACTSS_ASEN1;                         //enable sequence 1 - not initiated yet.
    28.  
    29. }
    30.  
    31. void delay(int dly) {
    32.     for (; dly>0; dly--)
    33.         ;
    34. }
    35.  
    36. int main(void) {
    37.     init_mcu();
    38.  
    39.     while (1) {
    40.  
    41.         ADC_PSSI_R |= ADC_PSSI_SS1;                             //initiate ss1 sequence - did this actually trigger an adc?
    42.         while (!(ADC_RIS_R & ADC_RIS_INR1)) {}                  //wait for ADC to complete;
    43.         ulSensor0Data = ADC_SSFIFO1_R;                          //retrive step 0 / adc0 result from sequence 1
    44.         ulSensor1Data = ADC_SSFIFO1_R;                          //retrive step 1 / adc2 result from sequence 1
    45.         ulSensor2Data = ADC_SSFIFO1_R;                          //retrive step 2 / adc1 result from sequence 1
    46.         ADC_ISC_R |= ADC_ISC_IN1;                               //clear the interrupt;
    47.         //delay(500);
    48.     }
    49. }
    50.  
    I am posting the code here in case some people may find it helpful.

    BTW, hardware oversamplingn still isn't working.
     
Loading...