Autor Tema: Asm embebido en C18 explicado  (Leído 8987 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado WillyP

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 280
    • Sitiónica
Asm embebido en C18 explicado
« en: 23 de Marzo de 2010, 01:53:41 »
Como se menciona tanto a C como Asm me pareció mejor dejarlo en este sector general de microcontroladores Pic, si es mejor otro subforo algún moderador lo moverá hacia allí.  

Esta explicación se limita solamente al compilador C18 bajo entorno MPLAB IDE y no abarca las diferencias que puedan existir para otros compiladores C.  

Empecemos con una breve síntesis:

Embeber código Asm en C es muy diferente a escribir instrucciones Asm “in line” del tipo: _asm  …..  _endasm
Las directivas anteriores para el compilador son limitadas y no se permite todo el repertorio de instrucciones que ofrece el microcontrolador. En cambio Asm embebido, mezclado o enfrascado en un compilador C equivale a poder integrar un código escrito en Asm, un programa completo en Asm, rutinas específicas en Asm, etc y llamadas desde C como a una función.
Como ejemplo se podría desarrollar 99% Asm  con 1% C sobre un compilador C, a la inversa o en cualquier porcentaje que decidiera el desarrollador. Es interesante tenerlo presente y aunque no es nada nuevo, tal vez no es del todo aplicado o conocido y lo más importante es la simpleza de su implementación siguiendo solamente las directivas especificas que requiere el compilador C. De esto se trata.

¿Ventajas? Las siguientes:

1-   Las ventajas sólo las puede encontrar el desarrollador según el proyecto, en mi caso no hay código en C18 que no tenga su cuota de rutinas con código Asm, pero es una decisión de cada programador.

2-   Una rutina en Asm puede ser en muchos casos más reducida, compacta y optimizada ya que la escribe directamente el desarrollador y no el analizador o intérprete de lenguaje del compilador.

3-   El C18 no hace uso del 100% del repertorio de instrucciones del microcontrolador, podríamos decir que un porcentaje de instrucciones quedan marginadas. Un claro ejemplo son:

CPFSEQ
CPFSGT
CPFSLT

Las anteriores instrucciones fueron incorporadas en los 18Fxxxx, especiales para comparaciones, y el C18 (por lo menos hasta la versión 3.32) no las utiliza en ningún momento.

4-   Para los programadores en Asm que comienzan en C es una forma de seguir con Asm e ir incorporando rutinas en C a medida que avanzan con el lenguaje o las librerías especializadas del C en sus proyectos Asm (desde asm pueden ser llamadas funciones en C)

5-   Para los programadores 100% C y quieren ir incursionado en Asm o utilizar librerías en Asm enlatadas en C.

6-   Fin del eterno dilema: todo “C” o todo “Asm”. La tercera opción es que pueden trabajar juntos y de maravilla.  ;-)


Requisitos: MPLAB IDE y tener instalado C18

Seleccionar C18 Toolsuite y crear un proyecto, salvando una plantilla con extensión .c y otra con extensión .asm

==================================================================================

// Desde el archivo .C

#include <p18cxxx.h>

// Declaración de variables globales

#pragma udata

char Registro_1;
char Registro_2;
char Registro_3;

// Prototipos de funciones

void Funcion_C(void);

// Declaración de las rutinas externas en ensamblador

extern void RUTINA_1(void);
extern void RUTINA_2(void);
extern void RUTINA_3(void);

// sección de código

#pragma code

void main(void){

// Desde main se llama a diferentes rutinas de ensamblador

RUTINA_1();
RUTINA_2();
RUTINA_3();
//…
//…
}

void Funcion_C(void){

// Esta función de C es llamada desde Asm
//…
//…
}

==================================================================================

;Desde el archivo .ASM:

; El clásico include según microcontrolador

        #include <p18f252.inc>

; Definiciones:

; Acá se pueden agregar definiciones, configuraciones como
; se hace habitualmente en ensamblador
; ......
; ......
; ......

; Variables:

; Las variables globales declaradas desde C pueden ser utilizadas desde las
; Rutinas Asm siempre y cuando sean declaradas en la cabecera del archivo Asm o
; bien desde un archivo .inc como externas:

; Ejemplo de variables char declaradas en C y utilizadas en Asm:

        EXTERN  Registro_1
        EXTERN  Registro_2
        EXTERN  Registro_3
;        .....
;        .....
 
; Código:

; Previo a rutinas de código Asm, debe declararse la directiva para el
; compilador:

      UDATA_ACS
      CODE

; La directiva CODE puede ampliarse si es necesario con el direccionamiento de memoria
; donde deberían iniciarse las secciones de código, para los programadores en Asm sería
; el reemplazo de la conocida directiva ORG 0xXX

SECTOR_1        CODE    0x0800

; SECTOR_1 puede ser cualquier nombre que identifique una dirección de memoria donde
; comenzará a ensamblarse el código, en este ejemplo a partir de la dirección 0x800.
; Para que no se genere error al compilar debe ser una dirección diferente a cualquiera
; que haya sido previamente declarada en C que direccionen un mismo sector de memoria.  

; Rutinas:

; RUTINA_1 o cualquier otro nombre, es la clásica etiqueta de Asm que hace
; referencia a una sección de código. Desde C18 es vista como una llamada a
; una función. Se finaliza con un RETURN y debe estar siempre presente la
; directiva GLOBAL <Nombre de rutina> en este caso GLOBAL RUTINA_1.
  
RUTINA_1:

        RCALL  Algoritmo
;        ......
;        ......

        RETURN

        GLOBAL RUTINA_1

; El código asm que sigue a RUTINA_1 puede llamar a otras rutinas dentro de Asm
; como se hace habitualmente con CALL o RCALL. Puede ser una rutina o bien un
; programa completo en asm.

; También desde el código ASM pueden ser llamadas Funciones de C, ejecutarse, retornar
; y continuar la rutina en ASM, para esto hay que declarar previamente (en la cabecera
; del archivo asm o creando un archivo .inc) la directiva "extern" a la función que luego será
; invocada desde alguna rutina asm.

; En la cabecera del archivo Asm de esta forma:

; EXTERN <Nombre de la función de C>

; desde una rutina:

; CALL <Nombre de la función de C>

; Ejemplo:

        EXTERN Funcion_C

; Esta rutina "Algoritmo" es llamada solamente por RUTINA_1
; dentro de Asm por lo tanto no necesita la directiva GLOBAL
; pero hace una llamada a una función escrita en C y retorna.
; La función en C está declarada como externa y es tomada desde
; el archivo Asm como otra etiqueta más dentro del programa.

Algoritmo:

        CALL Funcion_C
;       ......
;       ......
        
        RETURN

; RUTINA_2 y RUTINA_3 son ejemplos de rutinas que pueden ser llamadas
; por una o distintas funciones desde C

RUTINA_2:

;        ......
;        ......

        RETURN

        GLOBAL RUTINA_2

RUTINA_3:

;        ......
;        ......

        RETURN

        GLOBAL RUTINA_3

 ; Como todo programa en ASM no se debe olvidar finalizarlo con end

        END

;=================================================================================

; Las rutinas o programas en Asm pueden seguir utilizando también las directivas EQU,
; CBLOCK ... ENDC, etc, siempre teniendo precaución de no cambiar algún dato utilizado
; por alguna variable de C

; Para mayor información consultar "Mixing C and Assembly" del manual MPLAB® C18
; C COMPILER USER’S GUIDE.


 Adjunto el archivo C18 de lo explicado anteriormente para compilar. No tiene código, puesto que se trata de un ejemplo explicativo, es sólo para despejar alguna duda desde la práctica.
 Luego de compilar se debe hacer correr con el MPLAB SIM activado y comprobar como interactúan las llamadas entre C y ASM.

Saludos Willy.-


« Última modificación: 23 de Marzo de 2010, 02:27:28 por WillyP »

Desconectado bmfranky

  • PIC16
  • ***
  • Mensajes: 165
    • La Tienda De Fran
Re: Asm embebido en C18 explicado
« Respuesta #1 en: 23 de Marzo de 2010, 05:17:59 »
Una fantástica explicación , WillyP. Es una gran forma de reutilizar mis rutinas asm, en los programas que inicio ahora en C.
Visiten La Tienda De Fran ;-) Aqui. y mi nueva Web Aqui.

Desconectado LABmouse

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3575
    • Juntos es mejor
Re: Asm embebido en C18 explicado
« Respuesta #2 en: 16 de Enero de 2011, 20:02:05 »
Hola WillyP, Muchas gracias por la explicación.

En este momento me enfrento a mezclar C18 con ASM, pero necesito declarar asm en una que otra linea del archivo main.c.

Pretendo hacer esto:

 
Código: ASM
  1. _asm    BCF PORTA,0  _endasm

Pero me marca error sin saber como solucionarlo.

en cambio si intento esto:
Código: ASM
  1. _asm    goto initio  _endasm
Si funciona bien.. :?

Saben como declarar una linea asm de vez en cuando?

« Última modificación: 16 de Enero de 2011, 20:04:29 por LABmouse »

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Asm embebido en C18 explicado
« Respuesta #3 en: 16 de Enero de 2011, 20:25:24 »
Prueba implementadolo según datasheet:

Código: ASM
  1. _asm    BCF PORTA,0,0  _endasm
No contesto mensajes privados, las consultas en el foro

Desconectado LABmouse

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3575
    • Juntos es mejor
Re: Asm embebido en C18 explicado
« Respuesta #4 en: 16 de Enero de 2011, 20:58:57 »
Hola amigo Suky, Gracias!!!

Precisamente busque en el datasheet y encontre que

Código: ASM
  1. _asm bcf PORTA, 0, 1 _endasm


el ultimo digito es llamado segun datasheet "a"

RAM access bit:
a = 0: RAM location in Access RAM (BSR register is ignored)
a = 1: RAM bank is specified by BSR register

Cual debería usar para obtener el mejor resultado?..Pareciera según los ejemplos que encontré, que siempre usan 1.

Cual me recomiendan?¿?


Bueno pues compare con esta instruccion en C:

Código: C
  1. PORTAbits.RA0=0;

revise el código generado y encontré que al colocar en asm 0 en el bit "a", simplemente no trabaja. Cuando se coloca 0, tanto la que yo escribo en ASM como la generada del código en C son totalmente iguales..

SALUDOS!!



« Última modificación: 16 de Enero de 2011, 21:12:03 por LABmouse »

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Asm embebido en C18 explicado
« Respuesta #5 en: 16 de Enero de 2011, 21:33:01 »
El registro BSR es para seleccionar el Banco. No me he puesto a estudiar el asm de los 18F, pero generalmente veo que el disassembly utiliza ACCESS, o sea 0  :rolleyes:


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado bmfranky

  • PIC16
  • ***
  • Mensajes: 165
    • La Tienda De Fran
Re: Asm embebido en C18 explicado
« Respuesta #6 en: 29 de Julio de 2011, 16:23:39 »
Hola chicos, aunque el tema es ya viejo, como no había leído la respuesta, les expongo mi teoría al respecto... Jo que técnico.

Si ponemos el bsr a 1, el mismo compilador es el que rastrea los requerimientos del banco y selecciona la dirección correcta.

de otra forma, el compilador inserta directamente el código y si en ese momento habíamos accedido al banco 3 por ejemplo, intenta encontrar la dirección relativa al port A en este caso, pero no es correcta así que , no surte efecto la operación.

                                                                                                              bsr          dirección física        dirección relativa en la operación

por ejemplo pongamos que la dirección del port a es                                 1111          01101101                     111101101101 = F6D

pero hemos dicho que estamos en el banco 3 y no lo cambiamos                0011          01101101                     001101101101 = 36D

solución, en vez de poner a uno el pin que queríamos de el puerto A, hemos alterado un bit de una dirección errónea, que a saber que contenía, por ejemplo un contador, que no desbordara a tiempo y perderemos el flujo de programa.

Bueno, esta es mi teoria, si es una burrada, perdonad.
 pero supongo que sera un bug al incorporar el asembler, porque la forma correcta seria la primera ya que los puertos están en el access bank. a=0;
Visiten La Tienda De Fran ;-) Aqui. y mi nueva Web Aqui.