Inline assembly in C: INT command and C variables - c

I'm trying to use assembly in C code using C variables.
My code looks like this:
__asm { INT interruptValue };
Where 'interruptValue' is a variable I get from the user (e.g 15 or 15h).
When I try to compile I get:
Assembler error: 'Invalid instruction
operands'
I don't know what is the correct type for interruptValue . I tried long\int\short\char\char* but none of them worked.

The INT opcode does not allow to specify a variable (register or memory) as an argument. You have to use a constant expression like INT 13h
If your really want to call variable interrupts (and I cannot imagine any case for doing so), use something like a switch statement to decide which interrupt to use.
Something like this:
switch (interruptValue)
{
case 3:
__asm { INT 3 };
break;
case 4:
__asm { INT 4 };
break;
...
}
EDIT:
This is a simple dynamic aproach:
void call_interrupt_vector(unsigned char interruptValue)
{
//the dynamic code to call a specific interrupt vector
unsigned char* assembly = (unsigned char*)malloc(5 * sizeof(unsigned char));
assembly[0] = 0xCC; //INT 3
assembly[1] = 0x90; //NOP
assembly[2] = 0xC2; //RET
assembly[3] = 0x00;
assembly[4] = 0x00;
//if it is not the INT 3 (debug break)
//change the opcode accordingly
if (interruptValue != 3)
{
assembly[0] = 0xCD; //default INT opcode
assembly[1] = interruptValue; //second byte is actual interrupt vector
}
//call the "dynamic" code
__asm
{
call [assembly]
}
free(assembly);
}

Related

How to increment or decrement a 7-segment display 00-99 using button

i'm using code composer studio and data signals(D0-7) are obtained from tms320f28335
i have incremented and decremented specific led on 7-segment using switch statement. but that is kind if manual incrementing( where i already provide values as shown below)
void display(void)
{
B1 +=1;
if(B1 > B1_lim) { B1 = 0; }
switch(B1)
{
case 0: Display[0] = 0xf7; break; //9
case 1: Display[0] = 0xfF; break; //8
case 2: Display[0] = 0xf0; break; //7
case 3: Display[0] = 0x9F; break;
}
i have also tried to run counter but it never comes out of the loop because of while(1) statement and then i cant use other buttons, the code is shown below it works for 00-99 with never ending. furthermore, i tried to use button in below code but it loops like button can just start the increment/decrement process
void display(void)
{
unsigned char a[]={0xfb,0xb0,0xeD,0xf5,0xb6,0xd7,0x9F,0xf0,0xfF,0xf7}; //[0,1,2,3,4,5,6,7,8,9]
unsigned char b[]={0xfb,0xb0,0xeD,0xf5,0xb6,0xd7,0x9F,0xf0,0xfF,0xf7}; //[0,1,2,3,4,5,6,7,8,9]
int k,j;
while(1)
{
Display[0] = 0xfb;
Display[1] = 0xfb;
DELAY_US(200000L);
for(j=0;j<=9;j++)
{
Display[1]=b[j];
led_display(0x00); DELAY_US(200000L);
for(k=0;k<=9;k++)
{
Display[0] = a[k];
led_display(0x00); DELAY_US(200000L);
DELAY_US(2L);
}
}
}
}
on my 7-segment driver board, I have 4 buttons, and i want to use two of them for incrementing and decrementing.
I would like to know if there is any logical way to use a switch statement such that for each button press I can increment or decrement.
the simplest way show increment is shown in above code but i want to using second code.
I think you should use interrupt for button, don't use while(1) in your function.
Create a function to update value for 7-segment. When you press button, interrupt function will call. In this, you update your value to display.
First of all you need a coherent design following the tight cohesion, loose coupling principles. Your display function is attempting to doo too much - it is not cohesive - it contains logic related to your specific application and unrelated to display. It should do only what its name suggests and display a desired value. For example:
void display( uint8_t value )
{
// 0 1 2 3 4 5 6 7 8 9
static const uint8_t digits[]={0xfb,0xb0,0xeD,0xf5,0xb6,0xd7,0x9F,0xf0,0xfF,0xf7};
if( value < 100 )
{
uint8_t display[2] = {0,0} ;
display[0] = value % 10u ; // least significant digit
display[1] = value / 10u ; // most significant digit
led_display( 0x00 ) ;
}
}
Then let's assume (because you have not told us) that you have some GPIO input for the button and a clock source, hypothetically I will call these getSwitchState() and getClockMillisec(), then you might have a button state function something like:
bool getButtonState()
{
static const uint32_t DEBOUNCE_MILLIS = 20 ;
static uint32_t timestamp = getClockMillisec() ;
static bool debounced_button_state = getSwitchState() ;
uint32_t now = getClockMillisec() ;
uint32_t button_state = getSwitchState() ;
if( now - timestamp > DEBOUNCE_MILLIS &&
button_state != debounced_button_state )
{
debounced_button_state = button_state ;
timestamp = now ;
}
return debounced_button_state ;
}
Then you will want to act only on a button change of state, so you might have:
bool isButtonDownEvent()
{
static bool button_state = getButtonState() ;
bool button_down_event = false ;
// On change of state
if( getButtonState() != button_state )
{
button_state = !button_state ;
// True if button change was released to pressed (down event)
button_down_event = button_state ;
}
return button_down_event ;
}
Then your application loop can be built from those primitives thus:
uint8_t num = 0 ;
for(;;)
{
display( num ) ;
if( isButtonDownEvent() )
{
num++ ;
num %= 99 ;
}
}
Clearly if you have more than one button for separate increment/decrement that will need some modification to handle separate buttons, but since you have provided no information on the button hardware or software interface to it, I'll leave that to you to consider.
Also of course that is not the only possible solution to button input and debounce - you may already have suitable code. Usefully perhaps this method does not need a dedicated h/w timer or interrupt. It does however require regular polling to avoid missing events.
Critically note that the solution has no delays and no blocking, you can do other useful work in the loop whilst maintaining the display (so long as that too is non-blocking and does not take excessive CPU time such that button events might be missed.

C variable declared and assigned to function call

The local variable btmp in the below code is declared with an assignment to a function call. That function is reading the value of a register RegX. The next line writes to another register Reg_ADDR, which is the purpose of these lines of code. The lines thereafter potentially update btmp.
As this function does not return anything, is there any purpose to the last 4 lines of code? Or is there something complicated going on, e.g. btmp is some sort of pointer?
void SetDeviceAddress( uint8_t address, ENUM_MODE AddressMode)
{
uint8_t btmp = DeviceReadReg( RegX ) & ~0x03;
DeviceWriteReg(Reg_ADDR, address);
if ( AddressMode == MODE0 ) {}
else if( AddressMode == MODE1 ) { btmp |= 0x01; }
else if( AddressMode == MODE2 ) { btmp |= 0x02; }
else if( AddressMode == MODE3 ) { btmp |= 0x03; }
}
The 'btmp' variable is the local variable, so any write/change operations related to this are lost while clearing the stack on function return. Moreover, it seems that the first line of this code is useless too - as long as the DeviceReadReg() call has no side effects (if it has, this is really bad coding practice).
So, the real equivalent of the function is:
void SetDeviceAddress(uint8_t address, ENUM_MODE AddressMode)
{
DeviceWriteReg(Reg_ADDR, address);
}
or better:
void SetDeviceAddress(uint8_t address)
{
DeviceWriteReg(Reg_ADDR, address);
}

Passing PIN status as a function parameter

I want to write a function for my AVR ATmega328 that debounces switches using state space to confirm a switch press. After finishing it I wanted to generalize my function so that I may reuse it in the future with little work, but that involves passing the pin I want to use as a function parameter, and I just can't get that to work.
This is what I have now:
int debounceSwitch(unsigned char *port, uint8_t mask)
{
int n = 0;
while (1)
{
switch (n)
{
case 0: //NoPush State
_delay_ms(30);
if(!(*port & (1<<mask))){n = n + 1;}
else {return 0;}
break;
case 1: //MaybePush State
_delay_ms(30);
if(!(*port & (1<<mask))){n = n + 1;}
else {n = n - 1;}
break;
case 2: //YesPush State
_delay_ms(30);
if(!(*port & (1<<mask))){return 1;}
else {n = n - 1;}
break;
}
}
}
I have a hunch my issue is with the data type I'm using as the parameter, and I seem to have gotten different answers online.
Any help would be appreciated!
Well in AVR ports are special IO registers and they are accessed using IN and OUT instructions. Not like memory using LDR etc.
From the port definition you can see that you need to make the port pointer volatile. which the compiler would have also told you as a warning when you would had tried to pass PORT to the function.
#define PORTB _SFR_IO8(0x05)
which maps to
#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
Various issues:
The function should be void debounceSwitch(volatile uint8_t* port, uint8_t pin). Pointers to hardware registers must always be volatile. It doesn't make sense to return anything.
Never use 1 signed int literals when bit-shifting. Should be 1u << n or your program will bug out when n is larger than 8.
Burning away 30ms several times over in a busy-delay is horrible practice. It will lock your CPU at 100% doing nothing meaningful, for an eternity.
There are many ways to debounce buttons. The simplest professional form is probably to have a periodic timer running with interrupt every 10ms (should be enough, if in doubt measure debounce spikes of your button with a scope). It will look something like the following pseudo code:
volatile bool button_pressed = false;
void timer_interrupt (void)
{
uint8_t button = port & mask;
button_pressed = button && prev;
prev = button;
}
This assuming that buttons use active high logic.
What I dislike on your implementation is the pure dependency on PORT/IO handling and the actual filter/debouncing logic. What are you doing then, when the switch input comes over a signal e.g. from CAN?
Also, it can be handled much easier, if you think in configurable/parameterizable filters. You implement the logic once, and then just create proper configs and pass separate state variables into the filter.
// Structure to keep state
typedef struct {
boolean state;
uint8 cnt;
} deb_state_t;
// Structure to configure the filters debounce values
typedef struct {
uint8 cnt[2]; // [0] = H->L transition, [1] = L->H transition
} deb_config_t;
boolean debounce(boolean in, deb_state_t *state, const deb_config_t *cfg)
{
if (state->state != in) {
state->cnt++;
if (state->cnt >= cfg->cnt[in]) {
state->state = in;
state->cnt = 0;
}
} else {
state->cnt = 0;
}
return state->state;
}
static const deb_config_t debcfg_pin = { {3,4} };
static const deb_config_t debcfg_can = { {2,1} };
int main(void)
{
boolean in1, in2, out1, out2;
deb_state_t debstate_pin = {0, 0};
deb_state_t debstate_can = {0, 0};
while(1) {
// read pin and convert to 0/1
in1 = READ_PORT(PORTx, PINxy); // however this is defined on this architecture
out1 = debounce(in1, &debstate_pin, &debcfg_pin);
// same handling, but input from CAN
in2 = READ_CAN(MSGx, SIGxy); // however this is defined on this architecture
out2 = debounce(in2, &debstate_can, &debcfg_can);
// out1 & out2 are now debounced
}

program for interpretation of a simple instruction set

I have a problem I need to solve and I have no freaking idea how to do it. If someone would be willing to help I would very much appreciate it. I know I'm asking for a lot, but I really need it.
Create a program for interpretation of a simple instruction set consisting of the instructions: MVI, MOV, AND, OR, NOT, LESS, LEQ, GRE, GEQ, JMP, PRN, SUM, SUB, PRB, SL and SR, described in this document. Your task is to make a program that takes as an input a binary representation of a list of instructions, and as an output it prints the corresponding result (after the execution of the instructions). The input can contain all the instructions except SUB and PRB that you do not have to implement. Conversion from binary system to any other numeral system should not be made, except at the moment when you need to find the line that should be executed next when the condition is satisfied (GRE, GEQ, LESS, LEQ, JMP), but the comparison of the numbers in the condition should be made based on the binary representatio/pn. All data are represented in SM binary system. There are eight 16-bit registers available enumerated from 0 to 7.
#include<stdio.h>
#define MAX 1000
char registers[8][16];
void MVI(int reg, char *value) {
// code here
}
void MOV(int reg1, int reg2) {
// code here
}
void AND(int reg1, int reg2, int reg3) {
// code here
}
void OR(int reg1, int reg2, int reg3) {
// code here
}
void NOT(int reg1, int reg2) {
// code here
}
void PRN(int reg) {
// code here
}
void SUM(int reg1, int reg2, int reg3) {
// code here
}
void SL(int reg) {
// code here
}
void SR(int reg) {
// code here
}
int main() {
int i,j,k;
int N = 0; // number of lines in the input
char c;
char lines[MAX][16];
while (1) {
scanf("%c", &c);
if (c == '\n') {
break;
}
lines[N][0] = c;
for (i=1;i<16;i++) {
scanf("%c", &lines[N][i]);
}
N++;
scanf("%c", &c);
}
for (i = 0; i < 8; i++) {
for (j = 0; j < 16; j++) {
registers[i][j] = '0';
}
}
// code here
return 0;
}
I think the big piece you need is dispatching the functions based on the source line. There are a number of ways you can do this, but a useful piece for all of them is strstr(a,b)==a which will check if the string a begins with the contents of the string b.
You can do a chain of if-else blocks.
if (strstr(line[i], "SUM")==line[i]){
SUM(...);
} else if (strstr(line[i], "AND")==line[i]) {
AND(...);
}
Or you can precompile the user program by scanning for the opcodes when you read the source and store them as single-byte small codes. You would want the uppercase identifiers to be enum values, and use the lowercase versions for the function names. Then the chain is simpler.
if (line[i][0] == SUM) {
SUM(...);
} else if (line[i][0] == AND) {
AND(...);
}
But, with small integer codes, there are even better ways. A switch.
switch(line[i][0]){
case SUM: sum(...); break;
case AND: and(...); break;
}
A function table. But this is where you have be clever. A function must always be called with arguments of the correct type, but function-pointers allow you to bypass the compiler's ability
to check that this is so. So for this method, all functions should have the same arguments since
they are all called by a single function-call line.
void (*optab[])(...) = { sum, and, ... };
optab[ line[i][0] ](...); // calls sum() or and() by using the opcode in the array lookup

8051 Controller port bit reading / writing

The idea is to read any bit from a port.
Anyway accessing to one known bit is simple, like
P0_0 <-- gets bit 0 from port 0
But if i need to access bit y via function?
read_bit(__bit y){
return P0_y; // <-- just an idea but its not right becouse of syntax.
}
using SDCC to program and 8051 header.
If it's a literal constant, you can use a macro trick:
#define READ_P0_BIT(BIT) (P0_ ## BIT)
unsigned x = READ_P0_BIT(1);
If it's not a literal constant, you can do this:
int readP0bit(int bitNo)
{
switch (bitNo)
{
case 0: return P0_0;
case 1: return P0_1;
// ...
case 7: return P0_7;
default: return 0;
}
}
You can make a local array-variable that contains the bits in the function, and use the "bit" as an index into this array.
Something like:
__bit read_bit(const int b)
{
__bit all_bits[8] = {
P0_0,
P0_1,
/* etc. */
P0_7
};
return (b < 8 ? all_bits[b] : 0);
}
just see this function
char chek_bit_p0(unsigned char chk_bit){
if((P0>>chk_bit) & 1)
return 1;
else
return 0;
}
or simply by a macro like below (preferred way)
#define chek_bit_p0(x) (((P0>>x)&1)&&1)

Resources